获取属性类型并传递给泛型方法

时间:2013-03-28 10:18:28

标签: c# .net reflection

在.Net 4.5中工作。

我正在创建封装ActiveX控件的类(CadCorp SIS activeX控件是特定的),并基本上复制了该控件内部可用的一些对象(但不是外部)。从外部开始,必须使用带有文本字符串的API来操作内部对象的属性。

在每个课程中,我最终都会编写通过API获取和设置值的属性,而且我基本上是一遍又一遍的相同代码,例如: Control.GetInt(TargetDescripor, TargetIdentifier, PropertyName);,所以我尝试使用泛型将代码减少到最低限度。我现在有一个像这样的方法:

public T GetPropertyValue<T>(ObjectTypes Target, string PropertyName, int TargetIdentifier = 0)

标识正确的API方法并返回所需的值。

我仍然需要使用正确的描述符和正确的属性名称从每个对象调用此方法。我已经进一步减少了。例如,如果我在其中一个对象中获取属性,则使用以下代码:

public Class MyObject
{
    public bool MyObjectPropertyX
    {
        get { return this.GetProperty<bool>(); }
    }

    private const string _MyObjectPropertyX = "APICommandString";

    private T GetPropertyValue<T>([CallerMemberName] string PropertyName = null)
    {
        string apiCommand = (string)this.GetType().GetField("_" + PropertyName, BindingFlags.NonPublic | BindingFlags.Static).GetValue(this);

        // Call the method which executes the API command with the correct object
        // descriptor and get the value
    }
}

这很有用。

现在我想知道在属性的getter中是否有可能调用this.GetProperty<T>()并将type参数自动设置为属性的类型? 这可行吗?或者是我现在得到的最好的东西?

更新

另外,我很想知道转向这种方法是否有任何缺点。我将不得不进行大量的API调用,所以我想知道与原始代码相比,使用反射实际上是否会减慢这一点,我在每个getter和setter中明确地调用了适当的方法?

1 个答案:

答案 0 :(得分:1)

为了解决你的第一点,我认为你不会在没有过于复杂化的情况下进一步减少get代码;只是指定类型对我来说似乎很好。

如果您希望能够在不对字符串进行硬编码的情况下确定属性名称,则可以使用This method with reflection

关于表现,我首先要说的是:测试一下。如果您发现它很慢,那么您可以尝试缓存查找属性操作。此代码将反映的field.getValue调用包装在Func<string>中,以便每次都不需要反射查找。请记住,反射api无论如何都要在内部进行一些缓存,因此这可能没什么好处。

    private readonly IDictionary<String, Func<String>> _cache = new Dictionary<String, Func<String>>();

    private String GetApiCommand(String propertyName)
    {
        Func<String> command;
        if (_cache.TryGetValue(propertyName, out command))
        {
            return command();
        }

        var field = GetType().GetField("_" + propertyName, BindingFlags.NonPublic | BindingFlags.Static);//.GetValue(this);

        if (field != null)
        {
            Func<String> action = () => (String)field.GetValue(this);
            _cache[propertyName] = action;

            return action();
        }

        throw new NotSupportedException();
    }