Как привести объект к универсальному типу? - PullRequest
4 голосов
/ 21 июня 2011

У меня есть много классов, которые реализуют интерфейс IBuilder <> , такой как ниже

ОБНОВЛЕНО: каждая Model1, Model2 ... наследуется от IModel

public class A : IBuilder<Model1>
{
     public Model1 Create(string param)
     {
         return new Model1();
     }
}
public class B : IBuilder<Model2>
{
     public Model2 Create(string param)
     {
          return new Model2();
     }
}

Я использую StructureMap для регистрации всех классов, которые наследуют IBuilder <>

Scan(x =>
{
       x.TheCallingAssembly();
       x.AddAllTypesOf(typeof(IViewModelBuilder<>));                
});

ОБНОВЛЕНО

Сейчас,каждый раз, когда мне нужно получить модель какого-то модуля, я вызываю Do function

public IModel Do(Module module)
{
        //ModelSettings is taken from web.config  
        var builderType = Type.GetType(string.Format("{0}.{1}ModelBuilder,{2}", ModelSettings.Namespace, module.CodeName, ModelSettings.Assembly));
        var builder = ObjectFactory.GetInstance(t) as IViewModelBuilder<>;

        return builder.Create("");            
}

Я получаю ошибку компиляции в строке ObjectFactory.GetInstance(t) as IViewModelBuilder<>.Многие посты предлагают создать NOT универсальный интерфейс (IViewModelBuilder) и позволить универсальному наследовать его.И тогда я мог бы сделать кастинг как

ObjectFactory.GetInstance(t) as IViewModelBuilder

Это единственный способ?

Спасибо

Ответы [ 4 ]

5 голосов
/ 21 июня 2011

Ваш код для Do и GetInstance также должен быть универсальным. В основном это может выглядеть примерно так

public T Do<T> ()
{
     return ObjectFactory.GetInstance<T>().Create();
}
2 голосов
/ 21 июня 2011

Не могли бы вы сделать Do() родовым?

var m = Do<B>();

public T Do<T>()
{ 
   var builder = (IViewModelBuilder<T>)ObjectFactory.GetInstance(typeof(T));
   return builder.Create("");
}

Если вы не можете, лучше всего использовать не универсальный интерфейс, но есть и другие варианты, такие как использование отражения или C # 4 dynamic:

var m = Do(typeof(B));

public object Do(Type t)
{ 
   dynamic builder = ObjectFactory.GetInstance(t);
   return builder.Create("");
}
1 голос
/ 24 июня 2011

Вам необходимо ввести неуниверсальный интерфейс IViewModelBuilder, если вы хотите вызывать его в неуниверсальном сценарии.Универсальный IViewModelBuilder<T> будет реализовывать IViewModelBuilder.

Единственная другая альтернатива - вызвать метод create с помощью отражения, но я не понимаю, почему это будет предпочтительнее:

var builder = ObjectFactory.GetInstance(builderType);
var method = builderType.GetMethod("Create");
return (IModel) method.Invoke(builder, new[]{""});
1 голос
/ 21 июня 2011

Единственное, о чем я могу думать, это то, что вы создаете интерфейс или базовый класс, от которого наследуется ваша viewmodel. То есть:

public class Model1 : ModelBase
{
}

public class ModelBase
{
}

public ModelBase Do(Type t)
{
    var builder = ObjectFactory.GetInstance(t);
    return t.GetMethod("Create").Invoke(builder, new object[] { "" }) as ModelBase;
}
...