如何将一个对象转换为泛型类型?

4

我有许多实现了 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函数。

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<>这一行中遇到了编译错误。 许多帖子建议创建泛型接口(IViewModelBuilder),并让泛型接口继承它。然后我可以进行强制转换。
ObjectFactory.GetInstance(t) as IViewModelBuilder

这是唯一的方法吗?

谢谢


你的代码中混杂了真实代码和示例代码,非常令人困惑。IViewModelBuilder与IBuilder有何关联?A类的名称最终是否会以ModelBuilder结尾?等等。 - Joshua Flanagan
4个回答

5

你的DoGetInstance代码也应该是通用的。基本上它看起来应该像这样:

public T Do<T> ()
{
     return ObjectFactory.GetInstance<T>().Create();
}

我无法使Do成为通用的,因为我在运行时创建Do将接收的类型。 - theateist
我更新了我的帖子,并添加了我使用的真实代码。如果你能看一下,我会很高兴。 - theateist

2

您能将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("");
}

我无法使 Do 成为通用的,因为我在运行时创建 Do 将接收的类型。动态是否实用,还是重写我的代码会更好?如果我在运行时获取类型,我就不知道该如何重写了。 - theateist
在您的代码中似乎根本不需要泛型。只需使用非泛型的 IViewModelBuilder,它返回 IModel 即可。 - svick

1
我能想到的唯一方法就是创建一个接口或基类,让你的视图模型从中继承。例如:
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;
}

@Torbjon,我已经在使用某种ModelBase了。如果可以的话,我更新了我的帖子。我想避免使用Invoke,因为如果我将Create更改为Create2,我会忘记在GetMethod中更改它,但是使用真正的接口,如果我更改方法名称,我会得到编译错误。 - theateist

1
如果您想在非泛型场景中调用它,则需要引入一个非泛型的 IViewModelBuilder 接口。泛型的 IViewModelBuilder<T> 将实现 IViewModelBuilder
唯一的其他选择是通过反射调用 create 方法,但我不认为这是首选方法:
var builder = ObjectFactory.GetInstance(builderType);
var method = builderType.GetMethod("Create");
return (IModel) method.Invoke(builder, new[]{""});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接