-
Notifications
You must be signed in to change notification settings - Fork 471
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using ProxyGeneratorExtensions.CreateClassProxyWithTarget
Like ActivatorUtilities.CreateInstance
#532
Comments
ProxyGeneratorExtensions.CreateClassProxyWithTarget
together with ActivatorUtilities.CreateInstance
ProxyGeneratorExtensions.CreateClassProxyWithTarget
Like ActivatorUtilities.CreateInstance
Hi @lawrence-laz, |
Hi @stakx, Sorry for not being more attentive about the class being reffered. But Currently the following method: Question is would it be feasible to add an overload with |
It doesn't need to be known at compile time, but you'll have to use reflection to work that out if you want your application to proxy anything. I don't follow how a I'd suggest taking a read of the DynamicProxy docs (e.g. https://github.com/castleproject/Core/blob/master/docs/dynamicproxy-kinds-of-proxy-objects.md) to familiarise yourself with how DP works under the hood, creating the proxy instance isn't trivial which is why DP needs to do it for you. DP code generates the proxy type and creates an instance populating internal fields, for example the reference to your target object. |
The Maybe I still misunderstand, so let's look at that
|
I see that I underestimated the underying complexity of creating a proxy instance. Makes sense that you also need to initialize internal proxy state and a given type constructor arguments are just a part of it.
I hoped to avoid using reflection in this case by delegating object construction to type => ActivatorUtilities.CreateInstance(serviceProvider, type) To answer your questions:
I was thinking the generated proxy type.
Proxy.
Use it in the place where proxy is normally generated after calling a constructor with |
@lawrence-laz, perhaps the following will help when thinking about this. Imagine you want to create a proxy for the following type (let's just ignore the target business for now, whether your proxy has a target or not is mostly unrelated to the issue at hand): abstract class Frobbler
{
protected Frobbler(object arg) { ... }
} When DynamicProxy is asked to create a proxy, it has to create a proxy type first (which it then instantiates using class FrobblerProxy : Frobbler { ... } Now if you did this yourself, C# would at this point force you to add a constructor that calls one of the base class' constructors. So you'd have to add: class FrobblerProxy : Frobbler
{
public FrobblerProxy(object arg, ...) : base(arg) { ... }
} And there's your
I didn't reply to this earlier, but note that #480 is possibly related to this. |
Interesting. So using
Yes, but dependency container can! What I, as a user, would like to do is to replace proxy instantiation strategy with another in a format of So the default (currrent) would be: |
In that case you need to go one level lower. If you don't want DynamicProxy to create the proxy object for you, but the proxy type, then you'd use I should also mention that Also, you'll still need to pass |
@lawrence-laz to give a bit of perspective, Entity Framework Core uses this DynamicProxy API for all entity types and also passes https://github.com/dotnet/efcore/blob/main/src/EFCore.Proxies/Proxies/Internal/ProxyFactory.cs |
That gives me some ideas, thanks!
Yes, sorry, that would be class UserDependency { }
class UserClass
{
public UserClass(UserDependency userDependency) { ... }
}
class ProxyDependency { }
class UserClassProxy : UserClass
{
public UserClassProxy(ProxyDependency proxyDependency, UserDependency userDependency)
: base(userDependency) { ... }
}
class PseudoProxyGenerator
{
Func<Type, object[], object> ProxyFactory = (type, ctorArguments) => Activator.CreateInstance(type, ctorArguments);
public object CreateProxy(Type typeToProxy, object[] constructorArguments)
{
// ... creates proxy type, gather proxy arguments
var finalArguments = proxyArguments.Append(constructorArguments).ToArray();
return CreateProxyInternal(proxyType, finalArguments);
}
object CreateProxyInternal(Type proxyType, object[] constructorArguments)
{
return ProxyFactory.Invoke(proxyType, constructorArguments);
}
}
// User code
var serviceProvider = new ServiceCollection()
.AddTransient<UserDependency>()
.BuildServiceProvider();
var proxyGenerator = new ProxyGenerator();
proxyGenerator.ProxyFactory = (type, ctorArguments) => ActivatorUtilities.CreateInstance(serviceProvider, type , ctorArguments);
// User can provide an empty arguments array, because DI container will resolve UserDependency.
// While package makes sure to append ProxyDependency (not registered in user code/DI).
var proxy = ProxyGenerator.CreateProxy(typeof(UserClass), new [] { }); Does this make sense? |
To use
ProxyGeneratorExtensions.CreateClassProxyWithTarget
with non-parameterless constructors we have an overload withobject[] constructorArguments
.However, I don't think there is a way to delegate argument gathering responsibility to an outside party (ex. dependency container), like done in
ActivatorUtilities.CreateInstance
.Would it be feasible for
ProxyGeneratorExtensions.CreateClassProxyWithTarget
to provide an overload, which:ServiceProvider
instead ofobject[] constructorArguments
?ActivatorUtilities.CreateInstance
themselves?The text was updated successfully, but these errors were encountered: