1

寻找一种将关联数组传递给方法的方法。我正在寻找用 C# 重写一个 Actionscript 补间包,但遇到了“关联”数组/对象的问题。通常在 Actionscript 中,我可能会执行以下操作:

public function tween(obj:DisplayObject, params:Object = null):void {
    if (params.ease != null) {
        //do something
    }
    //...
}

这可以称为:

tween(this, {ease:'out', duration:15});

我正在寻找一种在 C# 中做同样事情的方法。到目前为止,我已经收集了我的选项:

a)创建一个类或结构来定义可能的参数键和类型并传递它

b) 将参数作为泛型类型传递

tween(frameworkElement, new {ease = 'out', duration = 15});

假设

public static void tween(FrameworkElement target, object parameters);

并找出一些在补间函数中使用它的方法(我不确定如何分离给定该对象的键=值。有什么想法吗?)

c) 创建一个Dictionary<string, object>将参数传递给补间函数

还有其他想法或示例代码吗?我是 C# 的新手。

编辑

花了我一整天才弄清楚:

“匿名类型不能跨程序集边界共享。编译器确保每个程序集中给定的属性名称/类型对序列最多有一个匿名类型。要在程序集之间传递结构,您需要正确定义它们。”

4

3 回答 3

1

我自己是选项 (b) 的粉丝——传递一个匿名类型并使用反射解析出值。

我已经看到其他人使用 lambda 表达式实现了同样的目标。调用语法是:

tween(frameworkElement, ease => "out", duration => 15);

声明将类似于以下内容:

public static void tween(FrameworkElement target, params Expression<Func<object>>[] parameters) { ... }

这个想法是您可以采用可变数量的“返回对象的函数”。然后,您从每个Expression<TDelegate>中解析出参数的名称,并调用每个来获取其值。

我不认为这比反映匿名类型更好,但这是另一种需要考虑的方法。

更新

实际上,我已经在我的博客herehere上写过将关联数组作为字典传递的想法。

于 2009-02-10T01:52:53.290 回答
1

字典是一种合理的方法。它可能看起来像这样:

public static void tween(FrameworkElement target, IDictionary<string, object> parameters)
{
    if (parameters.ContainsKey("ease")) {
        //do something
    }
}

请注意,当您传入值时,可以使用缩短的集合初始化语法使其更容易,例如:

tween(something, new Dictionary<string, object> { { "ease", "out" }, { duration, 15 } });

这将是一种非常快速的方式来完成与 ActionScript 代码大致“相同的事情”,但它并不是真正出色的 C#。C#-ish 的方法是创建一个真正的 TweenParameters 结构或类,为每个可能的参数提供属性,然后创建一个传递给 tween()。这通常被认为更易于维护,因为所有“可用”属性对于调用者来说都是显而易见的,而无需查看 tween() 的内部结构,并且因为它在编译时捕获错误,字符串比较直到运行时才会注意到,例如拼写“持续时间”“duratoin”。

于 2009-02-10T01:53:05.973 回答
1

编辑:这基本上是 HtmlHelper 扩展在 ASP.NET MVC 中使用的机制。这不是我原创的。


我更喜欢具有两个不同签名的混合方法。注意:我没有尝试过,两个签名之间可能存在冲突,因此您可能必须给第二种方法一个稍微不同的名称,以允许编译器在它们之间进行选择,但我不这么认为。

public static void tween( FrameworkElement target, object parameters )
{
    return tween( target, new ParameterDictionary( parameters ) );
}

public static void tween( FrameworkElement target,
                          ParameterDictionary values )
{
    if (values.ContainsKey( "ease" ))
    {
      ....
    }
}

然后你有一个 ParameterDictionary 类,它使用匿名类型的反射并设置字典。

public class ParameterDictionary : Dictionary<string,object>
{
    public ParameterDictionary( object parameters )
    {
         if (parameters != null)
         {
             foreach (PropertyInfo info in parameters.GetType()
                                                     .GetProperties())
             {
                 object value = info.GetValue(parameters,null);
                 this.Add(info.Name,value);
             }
         }
    }
}

这为您提供了易用性和易用性——“丑陋”的反射内容被包裹在字典的单个构造函数中,而不是在您的方法中。而且,当然,字典可以反复用于类似的目的,而反射代码只写一次。

于 2009-02-10T02:11:49.733 回答