C#不带泛型参数的泛型工厂返回

C#不带泛型参数的泛型工厂返回,c#,generics,factory,C#,Generics,Factory,我有下面的类和工厂(省略了不必要的代码)。我有3个独立的IManageableEntryDao实现,以及一个在createDao方法中访问的字符串/类型映射 我得到以下编译错误:“ManagableEntry.IManageableEntryDao”需要“1”类型参数”。解决这个问题的最佳实践是什么?我是否想以某种方式确定是什么?还是有其他解决办法 public interface IManageableEntryDao<T> where T : IManageableEntry {

我有下面的类和工厂(省略了不必要的代码)。我有3个独立的IManageableEntryDao实现,以及一个在createDao方法中访问的字符串/类型映射

我得到以下编译错误:“ManagableEntry.IManageableEntryDao”需要“1”类型参数”。解决这个问题的最佳实践是什么?我是否想以某种方式确定是什么?还是有其他解决办法

public interface IManageableEntryDao<T> where T : IManageableEntry {
    T findById(long id);
    T findByName(string name);

    int findUnapprovedCount();
    List<T> findUnapproved(ManageableEntryCriteria criteria);

    long insert(T manageableEntry);
    bool update(T manageableEntry);
    bool delete(T manageableEntry);
}

public class ManageableEntryDaoFactory {
    public IManageableEntryDao createDao(string manageableEntryType) {
            manageableEntryType = manageableEntryType.ToLower();
            Type type = daoTypes[manageableEntryType];
            if (type != null) {
                object dao = Activator.CreateInstance(type);                    
                return dao as IManageableEntryDao;
            }
            throw new NotImplementedException("Failed to find DAO for type: " + manageableEntryType);
        }
}
公共接口IManageableEntryDao其中T:IManageableEntry{
T findById(长id);
T findByName(字符串名称);
int findunprovedcount();
清单findUnapproved(ManagableEntryCriteria标准);
长插入(T ManagableEntry);
bool更新(T manageableEntry);
bool delete(T manageableEntry);
}
公共类ManagableEntryDaoFactory{
公共IManageableEntryDao createDao(字符串ManagableEntryType){
manageableEntryType=manageableEntryType.ToLower();
Type Type=daoTypes[manageableEntryType];
if(type!=null){
object dao=Activator.CreateInstance(类型);
将dao作为IManageableEntryDao返回;
}
抛出新的NotImplementedException(“未能找到类型:+ManagableEntryType的DAO”);
}
}

您需要在方法调用中指定类型。这意味着您可以避免使用字符串:

public IManageableEntryDao<T> CreateDao<T>() where T : IManageableEntry
{
        Type manageableEntryType = typeof(T);

        // You'll need to modify daoTypes to be a HashSet<Type> (or List<Type>) of allowable types, or something similar, instead of using a dictionary lookup
        if (daoTypes.Contains(manageableEntryType) {
            object dao = Activator.CreateInstance(type);                    
            return dao as IManageableEntryDao<T>;
        }
        throw new NotImplementedException("Failed to find DAO for type: " + manageableEntryType);
    }
public IManageableEntryDao CreateDao(),其中T:IManageableEntry
{
类型manageableEntryType=typeof(T);
//您需要将daoTypes修改为允许类型的哈希集(或列表)或类似的内容,而不是使用字典查找
if(daoTypes.Contains)(ManagableEntryType){
object dao=Activator.CreateInstance(类型);
将dao作为IManageableEntryDao返回;
}
抛出新的NotImplementedException(“未能找到类型:+ManagableEntryType的DAO”);
}
您可以:

  • 通过使
    CreateDao
    方法(或
    ManagableEntryDaoFactory
    本身)泛型,为
    IManageableEntryDao
    提供一个类型参数。 或者
  • CreateDao
    方法返回
    IManagableEntry
    接口,而不是返回泛型
    IManagableEntryDao
编辑:基于评论

不幸的是,您无法根据输入字符串从
CreateDao
方法返回特定类型。您最好返回一个基本类型或
daoTypes
列表中所有类型的通用接口

另一个想法是返回一个非泛型接口,并将接口强制转换为实现方法中的特定类型。下面是一个小程序来说明这一点:

class Program
{
    static void Main(string[] args)
    {
        var customerEntry = ManageableEntryDaoFactory.CreateDao("customer");
        var orderEntry = ManageableEntryDaoFactory.CreateDao("order");
        customerEntry.Update(new Customer() { Name = "John Doe" });
        orderEntry.Update(new Order() { OrderId = 123 });
        Console.ReadKey();
    }
}

public class Customer
{
    public string Name { get; set; }
}

public class Order
{
    public int OrderId { get; set; }
}

public class CustomerEntry : IManageableEntryDao
{
    public void Update(object objCustomer)
    {
        var customer = objCustomer as Customer;  // now you have a Customer type...
        Console.WriteLine("Updated customer: " + customer.Name);
    }
}

public class OrderEntry : IManageableEntryDao
{
    public void Update(object objOrder)
    {
        var order = objOrder as Order; // now you have an Order type... 
        Console.WriteLine("Updated order: " + order.OrderId);
    }
}

public interface IManageableEntryDao
{
    void Update(object entry);
    // ...other methods, properties, events...
}

public static class ManageableEntryDaoFactory
{
    private static readonly Dictionary<string, Type> daoTypes = new Dictionary<string, Type>() 
    {
        {"customer", typeof(CustomerEntry) }, 
        {"order", typeof(OrderEntry) }
    };

    public static IManageableEntryDao CreateDao(string manageableEntryType)
    {
        manageableEntryType = manageableEntryType.ToLower();
        Type type = daoTypes[manageableEntryType];
        if (type == null)
            throw new NotImplementedException("Failed to find DAO for type: " + manageableEntryType);

        return Activator.CreateInstance(type) as IManageableEntryDao;
    }
}
类程序
{
静态void Main(字符串[]参数)
{
var customerEntry=ManageableEntryDaoFactory.CreateDao(“客户”);
var orderEntry=ManageableEntryDaoFactory.CreateDao(“订单”);
Update(新客户(){Name=“John Doe”});
Update(新订单(){OrderId=123});
Console.ReadKey();
}
}
公共类客户
{
公共字符串名称{get;set;}
}
公共阶级秩序
{
公共int-OrderId{get;set;}
}
公共类CustomerEntry:IManageableEntryDao
{
公共无效更新(对象对象对象客户)
{
var customer=objCustomer as customer;//现在您有了一个客户类型。。。
Console.WriteLine(“更新的客户:+customer.Name”);
}
}
公共类OrderEntry:IManageableEntryDao
{
公共无效更新(对象对象对象)
{
var order=objOrder as order;//现在您有了一个订单类型。。。
Console.WriteLine(“更新订单:+order.OrderId”);
}
}
公共接口IManageableEntryDao
{
作废更新(对象条目);
//…其他方法、属性、事件。。。
}
公共静态类ManagableEntryDaoFactory
{
私有静态只读字典daoTypes=新字典()
{
{“客户”,类型(CustomerEntry)},
{“订单”,类型(订单条目)}
};
公共静态IManageableEntryDao CreateDao(字符串ManagableEntryType)
{
manageableEntryType=manageableEntryType.ToLower();
Type Type=daoTypes[manageableEntryType];
if(type==null)
抛出新的NotImplementedException(“未能找到类型:+ManagableEntryType的DAO”);
将Activator.CreateInstance(类型)作为IManageableEntryDao返回;
}
}

您需要将泛型参数添加到
createDao
ManagableEntryDAOFactory
,或显式指定类型参数。这不太有效,因为我需要实际返回DAO,以便对其调用方法。下面是我为使其工作所做的:公共类ManagableEntryDAOFactory where t:IManageableEntryDao{…公共IManageableEntryDao createDao(字符串ManagableEntryType){@AdamLevitt不幸的是,类型参数不能像那样动态传入。它必须在编译时已知。我实际如何调用此方法?我是否需要将泛型类型传入CreateDao的实际调用中?ManagableEntryDAOfactory.Instance.CreateDao()?@adamlevit
FooType foo=ManageableEntryDaoFactory.Instance.CreateDao()
然后你会得到具体的类型。对,但我实际上想传入一个类型字符串,而不是知道Dao类型。否则我可以直接创建Dao。这有意义吗?@adamlevit你怎么使用结果呢?@adamlevit你无法获得属性,因为它们是泛型的-所以它们是特定类型的。。。