2013-07-12 66 views
2

我有一个小类,它实现了一个从接口类型映射到从基类扩展的接口实现的字典。不幸的是,抽象基类没有实现接口,所以一旦在字典中,似乎没有办法将两者联系起来。在这个类中还有另一种方法,它依赖于将对象存储为BaseClass(实际上,我的大部分类都依赖于这个方法 - 入字典中的getter有点方便)。允许从接口转换为实现的通用约束

private readonly Dictionary<Type, BaseClass> dictionary; 

public void Add<T>(BaseClass base) 
{ 
    if (!(base is T)) // How to get rid of this check? 
    { 
     throw new ArgumentException("base does not implement " + typeof(T).Name); 
    } 

    this.dictionary.Add(typeof(T), base); 
} 

public T Get<T>() 
{ 
    BaseClass base; 
    this.dictionary.TryGetValue(typeof(T), out base); 
    return (T)(object)base; // How to get rid of (object) cast? 
} 

是否有任何聪明约束我可以使用以除去(碱T)检查,铸造到对象,或两者兼而有之?

这里是类设置,以供参考:

class BaseClass { } 
interface IThing { } 
class MyClass : BaseClass, IThing { } 

dict.Add<IThing>(new MyClass()); 
IThing myClass = dict.Get<IThing>(); 

回答

0

这是我最终使用的解决方案。有一些技巧可以使Add()在没有检查的情况下安全(请参阅cokeman19答案的评论中的链接),但是我选择不这样做,因为我觉得这个代码更简洁。

interface IThing { } 

abstract class BaseClass 
{ 
    internal T AsInterface<T> where T : class 
    { 
     return this as T; 
    } 
} 

class MyClass : BaseClass, IThing { } 

class DictionaryClass 
{ 
    private readonly Dictionary<Type, BaseClass> dictionary; 

    public void Add<T>(BaseClass base) 
    { 
     if (base is T) 
     { 
      dictionary.Add(typeof(T), base); 
     } 
    } 

    public T Get<T>() where T : class 
    { 
     return dictionary[typeof(T)].AsInterface<T>(); 
    } 
} 

请注意,此解决方案不会允许像电话:

myClass.AsInterface<IThingItDoesntImplement>() 

但这返回null,我所做的内部功能,以防止陌生的用途呢。

1

,如果你有编译型添加的派生类型的知识,让你要找的是编译时执行的唯一途径。

例如,如果您还指定要添加,则类的类型参数,你可以限制类实现的接口类型参数:

public void Add<TInterface, TClass>(TClass @base) 
     where TClass : BaseClass, TInterface { 
     this.dictionary.Add(typeof(TInterface), @base); 
    } 

所以,你可以这样做:

MyClass ok = new MyClass(); 
    dict.Add<IThing, MyClass>(ok); 

但不是这样的:

class MyClassNotIThing : BaseClass { } 

    MyClassNotIThing notOk = new MyClassNotIThing(); 
    dict.Add<IThing, MyClassNotIThing>(notOk); 

除此之外,泛型约束不提供了一种手段来约束已知类型(即, BaseClass)从泛型类型参数继承。

+0

我现在通过使用描述[这里](http://stackoverflow.com/questions/2893698/partial-generic-type-in​​ference-possible-in-c),现在大约一半的路径,我得到使用类型推断消除Add()中的检查。在Get()中放弃演员阵容可能比值得付出更多的努力,因为我知道演员由于通过Add()控制访问是安全的。 – lukegravitt