Как поместить интерфейс в универсальный динамически? - PullRequest
2 голосов
/ 30 июля 2010

У меня есть следующий тестовый класс:

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()
    {

    }
}

Это дает мне, однако, сообщение Type or namespace name expected. Как я могу настроить этот код, чтобы он работал?

То, что я пытаюсь сделать, это передать кучу интерфейсов в библиотеку классов, перебрать интерфейсы и использовать Unity для Разрешить что-то на основе интерфейса. Я использую метод расширения Resolve.

Ответы [ 4 ]

3 голосов
/ 30 июля 2010

Вам нужно будет использовать отражение ... примерно так:

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);
}

(Возможно, вам придется внести незначительные изменения - вышеприведенное не проверено и даже не скомпилировано.)

С помощью C # 4 и динамической типизации вы можете упростить задачу:

foreach (Type type in _interfaces)
{
    Type concreteType = typeof(Test<>).MakeGenericType(new Type[] { type });
    dynamic d = Activator.CreateInstance(concreteType);
    d.PerformSomething();
}
0 голосов
/ 30 июля 2010

Возможно, вы действительно захотите посмотреть на MEF в C # 4 как на идею, заменяющую единство. Я думаю, что он сам по себе очень хорошо работает и значительно упрощает механизмы разрешения и может дать функциональность для выполнения задачи, которую вы пытаетесь болеепросто ..

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 голосов
/ 30 июля 2010

Я не думаю, что это может сработать. Вы специализируете общий тип статически на имени типа. Вы не можете передать ссылку на объект Type.

Есть способы сделать то, что вы хотите, но они включают C # 4 и DynamicObject.

0 голосов
/ 30 июля 2010

Вы не можете передавать значения как общие аргументы.Только типы.Чтобы было понятно:

typeof (строка)! = Строка.

...