C# 使用 Dynamic 关键字通过字符串访问属性而不用反射

发布于 2024-08-31 05:48:26 字数 918 浏览 4 评论 0原文

我想写类似于以下内容的内容:

//  I will pass in a number of "properties" specified as strings that I want modified
string[] properties = new [] { "AllowEdit", "AllowDelete" };

//  Casting the component I'm using to a dynamic object of some sort ?
dynamic d = myGridComponent;

//  Iterate over the strings and set the properties
foreach(var s in properties) 
{
  //d.s = true; // 
  //d[s] = true; // this format would be ideal
}

我想知道是否有一种简单的方法可以在不使用反射 [.GetProperty(...).GetValue(...,...)] 使用新的 C# 4.0 关键字:dynamic

似乎可能有某种方法,...我只是不确定确切的机制,并且无法找到正确的资源将所有部分组合在一起。

想法?

[编辑] 看起来有一个名为“Clay”的包以某种方式实现了此类功能。 CodePlex 上的粘土
斯科特·汉塞尔曼谈这个主题

I would like to write something similar to the following:

//  I will pass in a number of "properties" specified as strings that I want modified
string[] properties = new [] { "AllowEdit", "AllowDelete" };

//  Casting the component I'm using to a dynamic object of some sort ?
dynamic d = myGridComponent;

//  Iterate over the strings and set the properties
foreach(var s in properties) 
{
  //d.s = true; // 
  //d[s] = true; // this format would be ideal
}

I was wondering if there was an easy way to do this without using Reflection [.GetProperty(...).GetValue(...,...)] using the new C# 4.0 keyword: dynamic.

It seems that there may be some way, ... I'm just not sure of the exact mechanism, and haven't been able to find the right resource to put all the pieces together.

Thoughts ?

[EDIT]
It looks like there is a package called "Clay" that implements this type of functionality in some way.
Clay on CodePlex
Scott Hanselman on the Subject

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

┾廆蒐ゝ 2024-09-07 05:48:27

这是可以做到的。您只需覆盖 DynamicObject 上的 TryGetIndex 即可。我需要类似的东西来调用类型的静态成员,但希望您能明白这个想法。请注意,这目前不适用于具有泛型类型参数的方法或重载的方法,从而限制了其实用性:

internal class StaticMembersDynamicWrapper : DynamicObject
{
    private readonly IDictionary<String, MemberInfo> staticMembers = new Dictionary<string, MemberInfo>();
    private readonly Type type;

    public StaticMembersDynamicWrapper(Type type)
    {
        this.type = type;
        type.GetMembers(BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public)
            .Each(member => staticMembers[member.Name] = member);
    }

    public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
    {
        var name = indexes[0] as string;

        MemberInfo member;

        if (false == staticMembers.TryGetValue(name, out member))
        {
            result = null;
            return false;
        }

        var prop = member as PropertyInfo;
        if (prop != null)
        {
            result = prop.GetValue(null, null);
            return true;
        }
        var method = member as MethodInfo;
        if (method != null)
        {
            var parameterTypes = (from p in method.GetParameters()
                                  select p.ParameterType).ToArray();
            var delegateType = method.ReturnType != typeof (void)
                            ? Expression.GetFuncType(parameterTypes.Union(new[]{method.ReturnType}).ToArray())
                            : Expression.GetActionType(parameterTypes);
            result = Delegate.CreateDelegate(delegateType, method);
            return true;
        }
        result = null;
        return false;
    }
}

dynamic d = new StaticMembersDynamicWrapper(typeof(string));
var result = d["IsNullOrEmpty"](String.Empty);

It can be done. You just have to override TryGetIndex on DynamicObject. I needed something similar to invoke static members of a type, but hopefully you will get the idea. Mind you this does not currently work on methods with generic type arguments or methods that are overloaded, limiting its utility:

internal class StaticMembersDynamicWrapper : DynamicObject
{
    private readonly IDictionary<String, MemberInfo> staticMembers = new Dictionary<string, MemberInfo>();
    private readonly Type type;

    public StaticMembersDynamicWrapper(Type type)
    {
        this.type = type;
        type.GetMembers(BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public)
            .Each(member => staticMembers[member.Name] = member);
    }

    public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
    {
        var name = indexes[0] as string;

        MemberInfo member;

        if (false == staticMembers.TryGetValue(name, out member))
        {
            result = null;
            return false;
        }

        var prop = member as PropertyInfo;
        if (prop != null)
        {
            result = prop.GetValue(null, null);
            return true;
        }
        var method = member as MethodInfo;
        if (method != null)
        {
            var parameterTypes = (from p in method.GetParameters()
                                  select p.ParameterType).ToArray();
            var delegateType = method.ReturnType != typeof (void)
                            ? Expression.GetFuncType(parameterTypes.Union(new[]{method.ReturnType}).ToArray())
                            : Expression.GetActionType(parameterTypes);
            result = Delegate.CreateDelegate(delegateType, method);
            return true;
        }
        result = null;
        return false;
    }
}

dynamic d = new StaticMembersDynamicWrapper(typeof(string));
var result = d["IsNullOrEmpty"](String.Empty);
锦欢 2024-09-07 05:48:27

不可以。C# 中的dynamic 不提供此功能。通过您的两个示例:

d.s = true; // this looks for a property or field called "s"
d[s] = true; // this looks for an indexer that matches the string/bool signature

您可以编写与动态提供的相同代码,但这比仅使用反射要困难得多。使用反射(根据您的示例),或者如果您需要优化它,您可以选择通过 ExpressionDelegate.CreateDelegate 将其包装在委托中。

No. dynamic in C# doesn't offer that. With your two examples:

d.s = true; // this looks for a property or field called "s"
d[s] = true; // this looks for an indexer that matches the string/bool signature

You can write the same code that dynamic offers, but it would be a lot harder than just using reflection. Either use reflection (as per your example), or if you need to optimise it you can optionally wrap it in a delegate, via either Expression or Delegate.CreateDelegate.

烟酉 2024-09-07 05:48:27

通过 nuget 提供的开源框架Impromptu-interface 封装了动态将在充满活力的时尚。它不如使用动态关键字快,但比反射更快。

foreach(var s in properties) 
{
  //d.s = true; 
  Impromptu.InvokeSet(d, s, true);
}

The opensource framework Impromptu-interface available via nuget encapsulates the code that dynamic would generate in a fully dynamic fashion. It's not as fast as using the dynamic keyword, but is faster than reflection.

foreach(var s in properties) 
{
  //d.s = true; 
  Impromptu.InvokeSet(d, s, true);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文