I need to combine multiple interfaces a runtime to create a new type. For example I might have the following interfaces:
public interface IA{
}
public interface IB{
}
At runtime I want to be able to generate another interface so that in the following sudo code works:
Type newInterface = generator.Combine(typeof(IA), typeof(IB));
var instance = generator.CreateInstance(newInterface);
Assert.IsTrue(instance is IA);
Assert.IsTrue(instance is IB);
Is there a way to do this in .Net C#?
It is possible because of power of Castle Dynamic Proxy
public interface A
{
void DoA();
}
public interface B
{
void DoB();
}
public class IInterceptorX : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine(invocation.Method.Name + " is beign invoked");
}
}
class Program
{
static void Main(string[] args)
{
var generator = new ProxyGenerator();
dynamic newObject = generator.CreateInterfaceProxyWithoutTarget(typeof(A), new Type[] { typeof(B) }, new IInterceptorX());
Console.WriteLine(newObject is A); // True
Console.WriteLine(newObject is B); // True
newObject.DoA(); // DoA is being invoked
}
}
Related
I want to register open generic interception, so I modified explample from https://github.com/dadhi/DryIoc/blob/master/docs/DryIoc.Docs/Interception.md
[TestFixture]
public class UnitTest3
{
public interface IFoo<T>
{
void Greet();
}
public class Foo<T> : IFoo<T>
{
public void Greet() { }
}
[Test]
public void Example()
{
var container = new Container();
container.Register(typeof(IFoo<>), typeof(Foo<>));
container.Register<FooLoggingInterceptor>(Reuse.Singleton);
container.Intercept<FooLoggingInterceptor>(typeof(IFoo<>));
var foo = container.Resolve<IFoo<int>>();
foo.Greet();
// examine that logging indeed was hooked up
var logger = container.Resolve<FooLoggingInterceptor>();
Assert.AreEqual("Invoking method: Greet", logger.LogLines[0]);
}
}
public class FooLoggingInterceptor : IInterceptor
{
public List<string> LogLines = new List<string>();
private void Log(string line) => LogLines.Add(line);
public void Intercept(IInvocation invocation)
{
Log($"Invoking method: {invocation.GetConcreteMethod().Name}");
invocation.Proceed();
}
}
public static class DryIocInterception
{
private static readonly DefaultProxyBuilder _proxyBuilder = new DefaultProxyBuilder();
public static void Intercept<TInterceptor>(this IRegistrator registrator, Type serviceType, object serviceKey = null)
where TInterceptor : class, IInterceptor
{
Type proxyType;
if (serviceType.IsInterface())
proxyType = _proxyBuilder.CreateInterfaceProxyTypeWithTargetInterface(
serviceType, ArrayTools.Empty<Type>(), ProxyGenerationOptions.Default); //Exception!!!
else if (serviceType.IsClass())
proxyType = _proxyBuilder.CreateClassProxyTypeWithTarget(
serviceType, ArrayTools.Empty<Type>(), ProxyGenerationOptions.Default);
else
throw new ArgumentException(
$"Intercepted service type {serviceType} is not a supported, cause it is nor a class nor an interface");
registrator.Register(serviceType, proxyType,
made: Made.Of(pt => pt.PublicConstructors().FindFirst(ctor => ctor.GetParameters().Length != 0),
Parameters.Of.Type<IInterceptor[]>(typeof(TInterceptor[]))),
setup: Setup.DecoratorOf(useDecorateeReuse: true, decorateeServiceKey: serviceKey));
}
}
But this throws exception:
Can not create proxy for type TestDryIoc.UnitTest3+IFoo`1 because type
TestDryIoc.UnitTest3+IFoo`1 is an open generic type.
Aparently Castle.Core doesn't support open generics. My other idea was to supply delegate, which will create the proxy class on resolve, when concrete generic param is known, but looks like DryIoc doesn't support open generic delegates...
Yeah, it is possible. So you need to find the closed type to pass it to the proxy? Wrap the code into the method and use the Made.Of which has access to the Request.ServiceType.
We have a simple data provider interface with covariant parameter definition.
interface IDataProvider<out T>
{
T Get();
}
The printer class will print the value of all IMessage.
class Printer
{
private readonly IEnumerable<IDataProvider<IMessage>> DataProviders;
public Printer(params IDataProvider<IMessage>[] dataProviders)
{
DataProviders = dataProviders;
}
public void Print()
{
foreach( var dataProvider in DataProviders)
{
Console.WriteLine( dataProvider.Get().Message );
}
}
}
interface IMessage
{
string Message { get; }
}
If all class implement one IDataProvider, the behavior is as my expectation. Following code will print "Hello" and "World".
class Program
{
static void Main(string[] args)
{
HelloProvider helloProvider = new HelloProvider();
WorldProvider worldProvider = new WorldProvider();
Printer printer = new Printer(helloProvider, worldProvider);
printer.Print();
}
}
class Hello : IMessage
{
public string Message { get; } = "Hello";
}
class World : IMessage
{
public string Message { get; } = "World";
}
class HelloProvider : IDataProvider<Hello>
{
public Hello Get() => new Hello();
}
class WorldProvider : IDataProvider<World>
{
public World Get() => new World();
}
However we have a bad boy implement two IDataProvider:
class BadBoy : IDataProvider<Hello>, IDataProvider<World>
{
// Assume that there are some shared state of Hello and World data.
Hello IDataProvider<Hello>.Get() => new Hello();
World IDataProvider<World>.Get() => new World();
}
I tried to cast BadBoy but Printer print two "Hello".
BadBoy badBoy = new BadBoy();
Printer printer = new Printer( (IDataProvider<Hello>)badBoy, (IDataProvider<World>)badBoy );
printer.Print();
The best solution we have now is separate IDataProvider implementation:
class HelloProvider : IDataProvider<Hello>
{
private readonly BadBoy BadBoy;
public HelloProvider(BadBoy badBoy)
{
BadBoy = badBoy;
}
public Hello Get() => BadBoy.GetHello();
}
class WorldProvider : IDataProvider<World>
{
private readonly BadBoy BadBoy;
public WorldProvider(BadBoy badBoy)
{
BadBoy = badBoy;
}
public World Get() => BadBoy.GetWorld();
}
class BadBoy
{
// Assume that there are some shared state of Hello and World data.
public Hello GetHello() => new Hello();
public World GetWorld() => new World();
}
I'm not satisfied with this solution because it may result in a lot of ceremonial codes as we continuously add new data type to our system. Is there better way to tell Printer class which implementation of IDataProvider it should use?
note:
This example is a simplified version of our real problem. In our project we resolve all IDataProvider from container and use reflection to create many calculation classes using those IDataProvider. Please tell me if you need more detail of the real problem.
You have painted yourself into a corner by duplicating a contract. However (and without making you redsign the whole solution), one approach (albeit nasty) would be to reflect out the interfaces by using GetInterfaces and GetInterfaceMap then invoking the method you need, you could potentially cache the MethodInfo, if need be.
Returns an interface mapping for the specified interface type.
Note : This may or may not be helpful to you (depending on your circumstances) ¯\_(ツ)_/¯
class Printer
{
public void Print()
{
foreach (var dataProvider in DataProviders)
{
var dataProviderType = dataProvider.GetType();
foreach (var type in dataProviderType.GetInterfaces())
{
var methodInfo = dataProviderType
.GetInterfaceMap(type)
.TargetMethods
.FirstOrDefault(x => x.Name.EndsWith("Get"));
var invoke = (IMessage) methodInfo.Invoke(dataProvider, null);
Console.WriteLine(invoke.Message);
}
}
}
...
Usage
BadBoy badBoy = new BadBoy();
Printer printer = new Printer(badBoy);
printer.Print();
Output
Hello
World
Update
using a MethodInfo cache
public List<MethodInfo> _cache;
public void Print()
{
foreach (var dataProvider in DataProviders)
{
var dataProviderType = dataProvider.GetType();
if (_cache == null)
{
_cache = dataProviderType.GetInterfaces().Select(x => dataProviderType.GetInterfaceMap(x)
.TargetMethods
.FirstOrDefault(x => x.Name.EndsWith("Get"))).ToList();
}
foreach (var item in _cache)
{
var invoke = (IMessage) item.Invoke(dataProvider, null);
Console.WriteLine(invoke.Message);
}
}
}
On my pc, i can call the original 100,000 times in 400ms, with the cache, i can call it, 100,000 times in 60ms.
I want to resolve some dependencies which will only be known at runtime. I am using configuration file to configure Unity (not programmatically).
Here is some code to show what I want to achieve.
Classes:
internal class WorkflowFactory : IWorkflowFactory
{
public IItemWorkflow GetWorkflow(string discriminator)
{
// return an implementation of IItemWorkflow as specified in config file
return null;
}
}
public interface IWorkflowFactory
{
IItemWorkflow GetWorkflow(string discriminator);
}
public interface IItemWorkflow
{
void Handle(int id);
// More methods
}
Usage:
internal class Program
{
private static void Main(string[] args)
{
IWorkflowFactory factory = new WorkflowFactory();
// I am using args to show I do not know the string until runtime
var wf1 = factory.GetWorkflow(args[0]);
var wf2 = factory.GetWorkflow(args[1]);
}
}
If you know a better way, I am totally open and invite suggestions.
Here is the class:
class Foo
{
private void Boo()
{
// Body...
}
// Other members...
}
What I need is:
Create a Foo2 class at runtime which has a copy of all Foo class members.
In Foo2 class replace Boo method by Boo2 method that has its content alternated to some extent.
Create an instance of Foo2 and invoke Boo2.
Thank you for help.
You can do it at runtime using a .NET AOP Framework event if it is not the the main purpose of this kind of framework.
I actively work on a new one which can handle it event if your method is not virtual.
You can take a look on NConcern .NET runtime AOP Framework
The monkey patch "aspect" :
public class MonkeyPatch : IAspect
{
static public void Patch(MethodInfo oldMethod, MethodInfo newMethod)
{
//update monkey patch dictionary
MonkeyPatch.m_Dictionary[oldMethod] = newMethod;
//release previous monkey patch for target method.
Aspect.Release<MonkeyPatch>(oldMethod);
//weave monkey patch for target method.
Aspect.Weave<MonkeyPatch>(oldMethod);
}
static private Dictionary<MethodInfo, MethodInfo> m_Dictionary = new Dictionary<MethodInfo, MethodInfo>();
public IEnumerable<IAdvice> Advise(MethodInfo method)
{
if (MonkeyPatch.m_Dictionary.ContainsKey(_Method))
{
yield return Advice(MonkeyPatch.m_Dictionary[_Method]);
}
}
}
Patch :
static public void main(string[] args)
{
//create Boo2, a dynamic method with Boo signature.
var boo2 = new DynamicMethod("Boo2", typeof(void), new Type[] { typeof(Foo) }, typeof(Foo), true);
var body = boo2.GetILGenerator();
//Fill your ILGenerator...
body.Emit(OpCodes.Ret);
//Apply the patch
MonkeyPatch.Patch(typeof(Foo).GetMethod("Boo"), boo2);
}
in the second hand, if you just need to call something after the original call, you are in AOP aim and you can do it like that...
Observation Aspect :
public class Observation : IAspect
{
static public void Observe(MethodInfo method, Action action)
{
//update observation dictionary
Observation.m_Dictionary[method] = action;
//release observation aspect for target method
Aspect.Release<Observation>(method);
//weave observation aspect for target method.
Aspect.Weave<Observation>(method);
}
static private Dictionary<MethodInfo, Action> m_Dictionary = new Dictionary<MethodInfo, Action>;
public IEnumerable<IAdvice> Advice(MethodInfo method)
{
if (Observation.m_Dictionary.ContainsKey(method))
{
yield return Advice.Basic.After(Observation.m_Dictionary[method]);
}
}
}
Use case :
static public void main(string[] args)
{
Observation.Observe(typeof(Foo).GetMethod("Boo"), () => { /* paste here your notification code... */ });
}
This is what I want to do in C# (within class Helper - without generic arguments),
List<AbstractClass<dynamic>> data;
public void Add<T>(AbstractClass<T> thing)
{
this.data.Add((AbstractClass<dynamic>) thing);
}
This helper class would take and work with AbstractClass<> objects and give back AbstractClass<> of specific generic type. AbstractClass<T> contains many functions which return T / take in T like public T Invoke().
For Helper class T cannot be known beforehand. The Add<T>(.. thing) function is not in a class of type T.
To be used like this in Helper class's functions,
foreach(var c in data.Where(x => ...))
{
// public T Invoke() { ... } function within AbstractClass<T>
var b = c.Invoke();
// logic
}
This also fails,
List<AbstractClass<object>> data;
public void Add<T>(AbstractClass<T> thing)
{
this.data.Add((AbstractClass<object>) thing);
}
Now I think I can have,
List<dynamic> data; // or List<object> data;
public void Add<T>(AbstractClass<T> thing)
{
this.data.Add(thing);
}
but I want the constraint that List named data has only elements of type like
ConcreteClass : AbstractClass<OtherClass>
So we would know that there is an public T Invoke() function but we do not know what it returns. This is helpful to avoid mistakes of say misspelling Invocke and only knowing at run-time.
I want to avoid casting to dynamic every time to invoke functions that give back generic type T
To do what you want to do you are going to need to use a Contravariant interface
public class Program
{
static void Main()
{
var m = new Helper();
m.Add(new ConcreteClass());
m.Process();
}
class Helper
{
List<IAbstractClass<OtherClassBase>> data = new List<IAbstractClass<OtherClassBase>>();
public void Add(IAbstractClass<OtherClassBase> thing)
{
this.data.Add(thing);
}
public void Process()
{
foreach(var c in data.Where(x => x.ShouldBeProcessed()))
{
var b = c.Invoke();
Console.WriteLine(b.Question);
var castData = b as OtherClass;
if (castData != null)
Console.WriteLine(castData.Answer);
}
}
}
public interface IAbstractClass<out T>
{
bool ShouldBeProcessed();
T Invoke();
}
abstract class AbstractClass<T> : IAbstractClass<T>
{
public bool ShouldBeProcessed()
{
return true;
}
public abstract T Invoke();
}
class ConcreteClass : AbstractClass<OtherClass>
{
public override OtherClass Invoke()
{
return new OtherClass();
}
}
class OtherClassBase
{
public string Question { get { return "What is the answer to life, universe, and everything?"; } }
}
class OtherClass : OtherClassBase
{
public int Answer { get { return 42; } }
}
}
You do not need to tell Add what kind of class you are passing it, all that matters is it derives from the type specified. You could do public void Add(IAbstractClass<object> thing) and every class would work, but Invoke() would only return objects inside the foreach loop.
You need to figure out what is the most derived class you want Invoke() to return and that is what you set as the type in the list.
Maybe this will work for you:
public class Program
{
static void Main()
{
var m1 = new Helper<OtherClass>();
m1.Add(new ConcreteClass());
var m2 = new Helper<int>();
m2.Add(new ConcreteClass2());
}
class Helper<T>
{
List<AbstractClass<T>> data = new List<AbstractClass<T>>();
public void Add<T1>(T1 thing) where T1 : AbstractClass<T>
{
this.data.Add(thing);
}
}
class AbstractClass<T> { }
class OtherClass { }
class ConcreteClass : AbstractClass<OtherClass> { }
class ConcreteClass2 : AbstractClass<int> { }
}