开发者

How to put an interface in a generic dynamically?

开发者 https://www.devze.com 2023-01-09 08:37 出处:网络
I have the following test class: public class OutsideClass { private List<Type> _interfaces = null;

I have the following test class:

public class OutsideClass
{
    private List<Type> _interfaces = null;

    public void InjectInterfaces(Type[] types)
    {
        if(_interfaces == null)
        {
            _interfaces = new List<Type>();
        }

        foreach (var type in types)
        {
            if(type.IsInterface)
            {
                _interfaces.Add(type);
            }
        }
    }

    public void PerformSomethingWithTheInterfaces()
    {
        foreach (var i in _interfaces)
        {
            new Test<i>().PerformSomething(); // On this line the error occurs
        }
    }
}

internal class Test<T>
{
    internal void PerformSomething()
    {

    }
}

This gives me on however the message Type or namespace name expected. How can I adjust this code so that it works?

What I am trying to do is to pass in a bunc开发者_运维百科h of interfaces to a class library, there loop over the interfaces and use Unity to Resolve, based on the interface, something. I use the Resolve extension method.


You'd need to use reflection... something like this:

foreach (Type type in _interfaces)
{
    Type concreteType = typeof(Test<>).MakeGenericType(new Type[] { type });
    MethodInfo method = concreteType.GetMethod("PerformSomething",
        BindingFlags.Instance | BindingFlags.NonPublic);
    object instance = Activator.CreateInstance(concreteType);
    method.Invoke(instance, null);
}

(You may need to make minor changes - the above isn't tested or even compiled.)

With C# 4 and dynamic typing, you can make it somewhat simpler:

foreach (Type type in _interfaces)
{
    Type concreteType = typeof(Test<>).MakeGenericType(new Type[] { type });
    dynamic d = Activator.CreateInstance(concreteType);
    d.PerformSomething();
}


You cannot pass values as generic arguments. Only types. To be clear:

typeof(string) != string.


I don't think this can work. You specialize a generic statically on the type name. You can't pass in a reference to the Type object.

There are ways to do what you want, but they involve C# 4 and DynamicObject.


You might really want to look at C# 4's MEF just as an idea as a unity replacement I think it stands up really well myself and simplifies the resolution mechanisms a lot, and may give functionality to complete the task you're attempting more simply..

namespace MEF_Interface
{
    // Interface to recognize the concrete implementation as
    public interface IMessageWriter
    {
        void WriteMessage();
    }

}

namespace MEF_HelloMessageWriter
{
    // Concrete implementation in another assembly
    [Export(typeof(IMessageWriter))]
    public class HelloMessageWriter : IMessageWriter
    {
        public void WriteMessage() { Console.WriteLine("Hello!"); }
    }
}

namespace MEF_GoodbyeMessageWriter
{
    // Concrete implementation in another assembly
    [Export(typeof(IMessageWriter))]
    public class GoodbyeMessageWriter : IMessageWriter
    {
        public void WriteMessage() { Console.WriteLine("Goodbye!"); }
    }
}

namespace MEF_Example
{
    class DIContainer
    {
        [Import]
        public IMessageWriter MessageWriter { get; set; }

        public DIContainer(string directory)
        {
            // No more messy XML DI definition, just a catalog that loads
            // all exports in a specified directory. Filtering is also available.
            DirectoryCatalog catalog = new DirectoryCatalog(directory);
            catalog.Refresh();
            var container = new CompositionContainer(catalog);
            container.ComposeParts(this);
        }
    }

    class Program
    {

        static void Main(string[] args)
        {
            string helloMessageWriterPath =
                @"C:\shared\Projects\MEF_Example\MEF_HelloMessageWriter\bin\Debug";

            string goodbyeMessageWriterPath =
                @"C:\shared\Projects\MEF_Example\MEF_GoodbyeMessageWriter\bin\Debug";

            DIContainer diHelloContainer = new DIContainer(helloMessageWriterPath);
            diHelloContainer.MessageWriter.WriteMessage();

            DIContainer diGoodbyeContainer = new DIContainer(goodbyeMessageWriterPath);
            diGoodbyeContainer.MessageWriter.WriteMessage();

            Console.ReadLine();
        }
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号