我试图通过提供使用泛型的工厂/构建器来抽象我的接口实现。但是,我在运行时遇到了多个调度和C#泛型的问题,这似乎有些奇怪。

基本方案是我定义了几个接口:

public interface IAddressModel
{
}

public interface IUserModel
{
}


然后,我有一个工厂类来返回实际的实现:

public class Factory
{
    public T BuildModel<T>()
    {
        return BuildModel(default(T));
    }

    public object BuildModel(object obj)
    {
        //this is here because the compiler will complain about casting T to
        //the first inteface parameter in the first defined BuildModel method
        return null;
    }

    public IAddressModel BuildModel(IAddressModel iModel)
    {
        //where AddressModel inherits from IAddressModel
        return new AddressModel();
    }

    public IUserModel BuildModel(IUserModel iModel)
    {
        //where UserModel inherits from IUserModel
        return new UserModel();
    }
}


问题是这样调用工厂时:new Factory().BuildModel<IAddressModel>()
在运行时从泛型分派的BuildModel(...)方法始终是T的最小派生形式,在这种情况下始终是对象。

但是,如果调用new Factory().BuildModel(default(IAddressModel));,则将分配正确的方法(很可能是因为这是在编译时完成的)。似乎使用泛型进行的动态分派不会检查大多数派生类型的方法,即使所调用的方法在编译时还是在运行时应相同。理想情况下,我想将BuildModel(...)方法设为私有,而只公开通用方法。还有另一种方法可以使动态调度在运行时调用正确的方法吗?我尝试将BuildModel<>()实现更改为return BuildModel((dynamic)default(T)),但这引发了关于无法确定要分派哪种方法的运行时错误。也许有一种方法可以通过矛盾和更多接口来做到这一点?

最佳答案

您可能可以根据参数类型T自己进行调度:

public class Factory
{
    private Dictionary<Type, Func<object>> builders = new Dictionary<Type, Func<object>>
    {
        { typeof(IAddressModel), BuildAddressModel },
        { typeof(IUserModel), BuildUserModel }
    };

    public T Build<T>()
    {
        Func<object> buildFunc;
        if (builders.TryGetValue(typeof(T), out buildFunc))
        {
            return (T)buildFunc();
        }
        else throw new ArgumentException("No builder for type " + typeof(T).Name);
    }

    private static IAddressModel BuildAddressModel()
    {
        return new AddressModel();
    }

    private static IUserModel BuildUserModel()
    {
        return new UserModel();
    }
}

10-07 12:08