2016-12-27 131 views
1

我在源格式和目标格式之间有m-to-n关联。 (现在,m = 2和n = 5,n增长快于m)。用相同的参数实例化不同的数据类型

我希望得到一个事件,输入格式是一个ItemDbDataReader,并将其转换成其他类型的,应当提供必要的构造函数:

public MyEvent(Item item) 
public MyEvent(DbDataReader ddr) 

public MyEventDetailed(Item item) 
public MyEventDetailed(DbDataReader ddr) 

public MyEventInfo(Item item) 
public MyEventInfo(DbDataReader ddr) 

public MyEventNotification(Item item) 
public MyEventNotification(DbDataReader ddr) 

public MyEventReminder(Item item) 
public MyEventReminder(DbDataReader ddr) 

每个构造是由只有一个使用两个数据存储:

EwsDataStore : DataStoreBase 
DbDataStore : DataStoreBase 

其现在各自实现从DataStoreBase抽象getEvent方法:

abstract MyEventDetailed getEvent(string uniqueId); 

现在我需要的所有其他目标格式一样,所以我要让他们一般是这样的:

abstract T getEvent<T>(string uniqueId) where T : IEvent, new() 

有可能EwsDataStore实现是

getEvent<T>(string uniqueId) where T : IEvent, new() // TODO: All affected models have to implement IEvent interface 
{ 
    Item item; 
    try { 
     item = Item.Bind(service, new ItemId(uniqueId)); 
    } catch(Exception e) { 
     throw new ArgumentException("An item by that Id was not found in the data store", "uniqueId", e); 
    } 
    // return T.FromItem(item); // Needs static IEvent.FromItem method. 
    return new T(item); // IEvent has to enforce constructor with parameter Item on all implementing classes 
} 

和SQL:

getEvent<T>(string uniqueId) where T:IEvent, new() // TODO: All affected models have to implement IEvent interface 
{ 
    SQL db = new SQL(); 
    db.AddParameter("@uniqueId", uniqueId) 
    SqlDataReader sdr = db.ExecuteReader("SELECT * FROM datastore WHERE uniqueId = @uniqueId"); 
    if(!sdr.HasRows) throw new ArgumentException("An item by that Id was not found in the data store"); 
    sdr.Read(); 
    // return T.FromDdr(sdr); // Needs static IEvent.FromDdr method. 
    return new T(sdr); // IEvent has to enforce constructor with parameter DataReader on all implementing classes 
} 

但既不是带参数的构造函数,也不是静态的方法将在一般类型被允许,每个抛以下两个错误消息之一:

修饰语“静态”是无效的这个项目
“T”:创建的实例时不能提供的参数变量类型

搜索这些错误消息;我发现"the instance method can simply (sic!) delegate to a static method",或者我可以使用ReflectionActivator

没有一个看起来足够简单/直接地写,理解,使用和维护。

是否有一种直接的方式使用继承和泛型来创建基于我提供的类型的所有不同类型,即使它们在C#继承中没有精通深入,其他程序员可以理解/遵循这些类型吗?

回答

1

首先,我想你是误解了new约束。 new意味着泛型类型T有一个无参数的构造函数new T(),这似乎与您想要的相反。

只要简单地除去new约束和使用Activator类中创建的T实例:Activator.CreateInstance

return (T)Activator.CreateInstance(typeof(T), item); 

另外,请注意,您不能在接口定义静态成员,也可以继承他们。因此,在语言中没有办法对通用类型T表达约束,这将允许您致电T.MyStaticMethod()

+0

这将意味着缺少构造函数会导致运行时错误,而不是编译时错误。是否有可能导致编译时错误? – Alexander

+0

@Alexander不,没有办法强制'T',以便它具有可访问的构造函数,而不管签名是什么。 'new'只强制'new T()'是一个有效的调用。 – InBetween

相关问题