2013-06-07 2 views
1

В настоящее время я работаю над абстракцией контейнера IoC, которая находится поверх StructureMap. Идея состоит в том, что он может работать и с другими контейнерами IoC.Передача аргументов методу, который должен использоваться для общего типа <T>?

public interface IRegister 
{ 
    IRegister RegisterType(Type serviceType, Type implementationType, params Argument[] arguments); 
} 

public abstract class ContainerBase : IRegister 
{ 
    public abstract IRegister RegisterType(Type serviceType, Type implementationType, params Argument[] arguments); 
} 

public class StructureMapContainer : ContainerBase 
{ 
    public StructureMapContainer(IContainer container) 
    { 
     Container = container; 
    } 

    public IContainer Container { get; private set; } 

    public override IRegister RegisterType(Type serviceType, Type implementationType, params Argument[] arguments) 
    { 
     // StructureMap specific code 
     Container.Configure(x => 
     { 
      var instance = x.For(serviceType).Use(implementationType); 
      arguments.ForEach(a => instance.CtorDependency<string>(a.Name).Is(a.Value)); 
     }); 

     return this; 
    } 
} 

public class Argument 
{  
    public Argument(string name, string value) 
    { 
     Name = name; 
     Value = value; 
    } 

    public string Name { get; private set; } 
    public string Value { get; private set; } 
} 

Я могу выполнить этот код, выполнив следующие действия:

//IContainer is a StructureMap type 
IContainer container = new Container(); 
StructureMapContainer sm = new StructureMapContainer(container); 

sm.RegisterType(typeof(IRepository), typeof(Repository)); 

Проблема возникает, когда я пытаюсь передать в качестве аргументов конструктора. StructureMap позволяет вам свободно перемещать все вызовы CtorDependency по своему желанию, но требует имени, значения и типа параметра конструктора. Так что я мог бы сделать что-то вроде этого:

sm.RegisterType(typeof(IRepository), typeof(Repository), new Argument("connectionString", "myConnection"), new Argument("timeOut", "360")); 

Этот код работает как CtorDependency в настоящее время типа строки и оба аргумента являются строками, а также.

instance.CtorDependency<string>(a.Name).Is(a.Value) 

Как передать несколько аргументов конструктора BUT любого типа этому методу? Является ли это возможным? Любая помощь приветствуется.

+0

Вопрос: Почему вы не используете что-то вроде 'RegisterType (...)'? – Femaref

+0

У меня есть методы расширения, которые имеют эту подпись, но я решил включить только нужный код, чтобы проиллюстрировать проблему. – Thomas

+0

Ах, правильно. Что касается вашего вопроса: я думаю, вы не сможете обойтись здесь, используя рефлексию, но это должно быть целесообразно использовать здесь. – Femaref

ответ

2

Вы можете использовать динамический анонимный объект для передачи своих аргументов. Затем используйте отражение, чтобы проверить свойства. Значения могут быть любого типа.

dynamic example = new 
{ 
    a = 3, 
    b = "hello" 
}; 

foreach (PropertyInfo p in example.GetType().GetProperties()) 
{ 
    string key = p.Name; 
    dynamic value = p.GetValue(example, null); 
    Console.WriteLine("{0}: {1}", key, value); 
} 

Это выводит

: с 3
б: привет

Просто измените по мере необходимости для ваших нужд.

Edit:

Просто так это понятно. Ваш метод регистрации будет иметь динамический параметр. Это было бы что-то вот так. У меня нет StructureMap, но это должно помочь вам в правильном направлении.

public override IRegister RegisterType(Type serviceType, Type implementationType, dynamic arguments) 
{ 
    // StructureMap specific code 
    Container.Configure(x => 
    { 
     var instance = x.For(serviceType).Use(implementationType); 
     foreach (PropertyInfo p in arguments.GetType().GetProperties()) 
     { 
      string key = p.Name; 
      object value = p.GetValue(arguments, null); 
      instance.CtorDependency<string>(key).Is(value)); 
     } 
    }); 

    return this; 
} 

Edit Part Deux:

Хорошо, так что Вы желаете, чтобы иметь возможность передавать в любой тип данных для ключа. Это ближе к тому, что вам нужно? Вы получаете метод по имени, превращаете его в закрытый общий, вызывая MakeGenericMethod. Затем вы вызываете его.

var method = instance 
    .GetType() 
    .GetMethod("CtorDependency") 
    .MakeGenericMethod(new Type[] { key.GetType() }); 
method.Invoke(instance, new object[] { key }); 
+0

Эми, я думаю, что я сделал плохую работу, подчеркивая, где основная проблема. Он находится в этой строке: instance.CtorDependency (ключ) .Is (value)), где T в настоящее время является строкой.Этот код находится внутри цикла foreach. Вопросы становятся тем, что происходит, если первым аргументом является int, второй - bool, а затем строка ... как это сделать, чтобы преобразовать это в instance.CtorDependency (ключ) .Is (value)) then instance.CtorDependency (ключ) .Is (значение)) и, наконец, экземпляр.CtorDependency (ключ) .Is (значение))? – Thomas

+0

Я обновлю свой ответ. Дайте мне немного. – Amy

+0

Эми, я думаю, вы поняли. Я еще не пробовал код, но он точно выглядит в правильном направлении. Спасибо! – Thomas

Смежные вопросы