可以将SomeClass <t>转换为SomeClass <object>,其中T直到运行时才“已知”?</object> </t>

时间:2014-01-29 00:15:59

标签: c# generics reflection

为什么我遇到这个问题会在下面带有KnownValueDefinition<T>的示例中显示,理想情况下,我希望能够从静态类中输出List<KnownValueDefinition<object>>一堆静态只读{{1} }}Š

KnownValueDefinition<T>

其中var reflectedFields = typeof(KnownValue) .GetFields( BindingFlags.Static | BindingFlags.Public ) .Where( p => p.FieldType.GetGenericTypeDefinition() == typeof(KnownValueDefinition<>) ); foreach( var fieldInfo in reflectedFields ) { object value = fieldInfo.GetValue( null ); // every conversion method I've tried here fails... } 基本上定义为:

KnownValueDefinition<T>

3 个答案:

答案 0 :(得分:1)

您可以定义和实现协变接口:

public interface IKnownValueDefinition<out T> 
{
    public string Key { get; }
    public T DefaultValue { get; }
}

public class KnownValueDefinition<T> : IKnownValueDefinition<T>
{
    // .. private members excluded for brevity
    public string Key { get { return _key; } }
    public T DefaultValue { get { return _defaultValue; } }
}

用法:

var kvdSomeClass = new KnownValueDefinition<SomeClass>();
IKnownValueDefinition<object> kvdObject = kvd; // this works

// but this will not work
var kvdInt = newKnownValueDefinition<int>();
kvdObject = kvdInt;

Covariance & Contravariance MSDN Page

答案 1 :(得分:1)

简短的回答是否定的。

给出两个类:

class BaseClass { ... }
class DerivedClass : BaseClass { ... }

和通用类

class Widget<T> { ... }

这是实例化

Widget<BaseClass> {...}
Widget<DerivedClass> { ... }

几乎被视为独立的类。你不能这样“upcast”:

Widget<DerivedClass> instance = new Widget<DerivedClass>() ;
Widget<BaseClass>    upcastInstance = (Widget<DerivedClass>)instance ;

即使它似乎是一个完美的理想的事情。

此外,C#(以及CLR?)无法说出像

这样的内容
Widget<?> = instance = ... ;

表示我关心的是Widget<T>的某个实例,但我并不关心T的类型。

关于这个主题有很多问题(和答案):只搜索。

答案 2 :(得分:0)

阿列克谢的评论给了我一个看似完美的想法(至少对我而言)!:

public class KnownValueDefinition<T> :
      IKnownValueDefinition
    , IKnownValueDefinition<T>
{
    // .. private members excluded for brevity
    public string Key { get { return _key; } }
    public T DefaultValue { get { return _defaultValue; } }

    public KnownValueDefinition( string key, T DefaultValue )
    {
        //...construction logic
    }

    public IKnownValueDefinition<object> GetDefault()
    {
        return new KnownValueDefinition<object>( this._key, this._defaultValue );
    }
}

public interface IKnownValueDefinition
{
    IKnownValueDefinition<object> GetDefault();
}

public interface IKnownValueDefinition<out T>
{
    string Key { get; }
    T DefaultValue { get; }
}

并使用使用场景完成此操作:

var knownValueDefinitions = new List<IKnownValueDefinition<object>>();

var reflectedFields =
    typeof(KnownValue)
    .GetFields( BindingFlags.Static | BindingFlags.Public )
    .Where( p => p.FieldType.GetGenericTypeDefinition() == typeof(KnownValueDefinition<>) );

foreach( var value in reflectedFields.Select( fieldInfo => fieldInfo.GetValue( null ) ) )
    KnownValueDefinitions.Add( ((IKnownValueDefinition)value).GetDefault() );