访问类型在运行时已知的对象的属性

时间:2014-09-04 07:47:17

标签: c# linq expression-trees

我有一个对象,其基类型在编译时公开,但其运行时类型是内部的,并且出于所有实际目的,我无法在编译时获取该类型。

但是,我希望能够在运行时访问其实例上的属性。

据我所知,在编译时不知道类型,我无法创建一个类型化的委托。

访问此属性的最佳方式是什么? DynamicInvoke?

想象一下这是一个文件:Hidden.cs

 internal class Hidden
 {
     public string SomeProp { get { .. } }
 }

我无法在我的代码中键入以下内容Func someExpression = Expression.Lambda< Func<程序,字符串> > ...

我只想在编译时无法引用该类型时确认我唯一的选项是DynamicInvoke。

2 个答案:

答案 0 :(得分:1)

您可以创建Func<object, string>,然后将object转换为Hidden(您的类型),然后访问SomeProp。所有这些都可以在这样的表达式中完成:

internal class Program
{
    private static Func<object, string> somePropFunc;
    private static void Main(string[] args)
    {
        //Create instance somehow
        Type type = typeof(Hidden);
        object hiddenInstance = Activator.CreateInstance(type);

        //Cache the delegate in static field, and use it any number of times
        somePropFunc = GetSomePropAccessorMethod();
        for (int i = 0; i < 100; i++)
        {
            // Access Hidden.SomeProp
            Console.WriteLine(somePropFunc(hiddenInstance));
        }
    }

    private static Func<object, string> GetSomePropAccessorMethod()
    {
        Type type = typeof(Hidden);
        PropertyInfo prop = type.GetProperty("SomeProp");
        var parameter = Expression.Parameter(typeof(object), "hidden");
        var castHidden = Expression.TypeAs(parameter, type);
        var propertyAccessor = Expression.Property(castHidden, prop);
        return Expression.Lambda<Func<object, string>>(propertyAccessor, parameter).Compile();
    }

}

internal class Hidden
{
    public string SomeProp
    {
        get
        {
            return "Some text";
        }
    }
}

哪些打印&#34;一些文字&#34;在控制台100次。

答案 1 :(得分:0)

您始终可以使用dynamic代理,例如Func<dynamic,T>,T代表您的返回类型。但请记住,动态调度“缓慢”,因为它使用了scènes背后的反射。 DynamicInvoke完全相同,所以它也一样慢。

现在请记住,“慢”非常相对。与静态调用相比,它很慢,几乎是即时的,但这种微优化在实际程序中几乎不可见。

此外,为什么你需要首先调用一个未知类型的对象的属性?对我来说,这听起来就像是在某个地方做出糟糕的设计决定的症状。例如,考虑让相关类型从公共基类继承/实现相同的接口,突然你的问题消失了。而且你可以获得更好的表现作为奖励。

修改

我一开始并没有意识到您想要访问一个您无法看到的成员。那么反思是你唯一的希望。而且您还需要完全信任地运行您的代码。请记住,班级的原创者决定不让你访问这个成员,他可以有很好的理由。你不应该这样做,除非你真的不能这样做。