哪个更好Params或List

时间:2014-04-29 07:52:12

标签: c# .net

我当前的代码如下,它是作为客户端代理公开的WCF服务方法:

public UnifiedDTO GetAllCardTitle(string trainSymbolOrCarLocation, 
                                  DateTime startDate, 
                                  DateTime endDate, 
                                  string procedureName = CardTitle.procedureNameTrainRuns)

此方法采用过程名称(作为最后一个参数),其余参数是绑定输入参数,但问题是我们在参数编号和类型更改的情况下没有灵活性。该项目尚处于初始阶段,因此肯定会有所改变。

我拥有的选项是按如下方式转换方法:

public UnifiedDTO GetAllCardTitle(params object [] parameters)

我们可以自由地传递参数和程序细节,并可以相应地绑定。但是,由于装箱和拆箱,可能会出现性能问题。它需要客户端应用程序以正确的顺序和值传递参数,以便像底层图层所期望的那样进行绑定

public UnifiedDTO GetAllCardTitle(List<Filter> parameter, string procedureName)

Parameter类定义为:

public class Filter
{
    public string name { set; get; }
    public string value { set; get; }
    public string dataTypeID { set; get; }

    public Filter(string _name, string _value, string _dataTypeID)
    {
        name = _name;
        value = _value;
        dataTypeID = _dataTypeID;
    }
}

在给定过程的此方法中,我们将每个参数与其名称值和DataType绑定,并且需要将值转换为正确的数据类型,它比最后一个方法具有更大的灵活性并且可以传递以任何顺序,因为绑定是按名称。但是,它需要从应用程序中进行更多的尽职调查。

使用C#.Net中引入的新内容还有更好的方法来处理这种情况吗?

2 个答案:

答案 0 :(得分:1)

无。 Use Dynamic反对

要创建一个与DLR一起使用的C#类,最简单的方法是从DynamicObject派生。尝试在WCF服务中使用动态类型时会出现一个限制。在尝试使用WCF的DataContractSerializer进行序列化时,尝试使用DynamicObject派生类型将导致运行时异常。

[DataContract]
public class SerializableDynamicObject : IDynamicMetaObjectProvider
{
[DataMember]
private IDictionary<string,object> dynamicProperties = new Dictionary<string,object>();

#region IDynamicMetaObjectProvider implementation
public DynamicMetaObject GetMetaObject (Expression expression)
{
    return new SerializableDynamicMetaObject(expression, 
        BindingRestrictions.GetInstanceRestriction(expression, this), this);
}
#endregion

#region Helper methods for dynamic meta object support
internal object setValue(string name, object value) 
{
    dynamicProperties.Add(name, value);
    return value;
}

internal object getValue(string name) 
{
    object value;
    if(!dynamicProperties.TryGetValue(name, out value)) {
        value = null;
    }
    return value;
}

internal IEnumerable<string> getDynamicMemberNames() 
{
    return dynamicProperties.Keys;
}
#endregion
}


public class SerializableDynamicMetaObject : DynamicMetaObject
{
Type objType;

public SerializableDynamicMetaObject(Expression expression, BindingRestrictions restrictions, object value) 
    : base(expression, restrictions, value) 
{
    objType = value.GetType();
}

public override DynamicMetaObject BindGetMember (GetMemberBinder binder)
{
    var self = this.Expression;
    var dynObj = (SerializableDynamicObject)this.Value;
    var keyExpr = Expression.Constant(binder.Name);
    var getMethod = objType.GetMethod("getValue", BindingFlags.NonPublic | BindingFlags.Instance);
    var target = Expression.Call(Expression.Convert(self, objType),
                                 getMethod,
                                 keyExpr);
    return new DynamicMetaObject(target,
        BindingRestrictions.GetTypeRestriction(self, objType));
}

public override DynamicMetaObject BindSetMember (SetMemberBinder binder, DynamicMetaObject value)
{
    var self = this.Expression;
    var keyExpr = Expression.Constant(binder.Name); 
    var valueExpr = Expression.Convert(value.Expression, typeof(object));
    var setMethod = objType.GetMethod("setValue", BindingFlags.NonPublic | BindingFlags.Instance);
    var target = Expression.Call(Expression.Convert(self, objType),
    setMethod, 
    keyExpr, 
    valueExpr);
    return new DynamicMetaObject(target,
        BindingRestrictions.GetTypeRestriction(self, objType));
}

public override IEnumerable<string> GetDynamicMemberNames ()
{
    var dynObj = (SerializableDynamicObject)this.Value;
    return dynObj.getDynamicMemberNames();
}
}

一个警告,动态成员可以是任何东西,这意味着在运行时有人可以将方法分配给其中一个字段。如果在您的应用程序中可以实现,则需要确保分配给动态类型的任何方法都不是序列化的。我将此作为练习留给读者。

Taken from Here

答案 1 :(得分:1)

是否可以允许&#34; Interfaced&#34;参数。从那里,你可以根据接口值设置处理多个事情。只拍出一个简单的样本。

public enum eWhatAmI
{
   ListedObjects,
   StringArrays,
   Other   
}

public interface IWhatParmType
{
   eWhatAmI whatAmI { get; set; }
}

public class MyListVersion : IWhatParmType
{
   public eWhatAmI whatAmI { get; set; }
   public List<string> whatever { get; set; }

   public MyListVersion()
   {
      whatAmI = eWhatAmI.ListedObjects;
      whatever = new List<string>();
      ... build out list of strings
   }
}

public class MyArrayVersion : IWhatParmType
{
   public eWhatAmI whatAmI { get; set; }
   public string[] whatever { get; set; }

   public MyArrayVersion()
   {
      whatAmI = eWhatAmI.StringArrays;
      ... build out array of strings
   }
}

等...

然后在处理传入参数的过程中,您可以处理任何一种方式。

public UnifiedDTO GetAllCardTitle(IWhatParmType parameter, string procedureName)
{
   switch( parameter )
   {
      case (eWhatAmI.ListedObjects):
         // Just for grins, test to make sure object really IS expected list version object
         if( parameter is MyListVersion)
            DoViaList( (MyListVersion)parameter );
         break;

      case (eWhatAmI.StringArrays ):
         if( parameter is MyArrayVersion )
            DoViaArray( (MyArrayVersion)parameter );
         break;
   }
}

private void DoViaList( MyListVersion parm1 )
{
   .. do whatever based on the "List<string>" property
}

private void DoViaArray( MyArrayVersion parm1 )
{
   .. do whatever based on the "string []" property
}

然后,如果您需要扩展每个特定对象实例的设置,您可以在特定的子处理程序方法中处理,以填充或强制隐含默认值。