哪个更好Params或List

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

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

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

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

 public UnifiedDTO GetAllCardTitle(params object [] parameters) 

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

 public UnifiedDTO GetAllCardTitle(List 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中引入的新东西,还有更好的方法来处理这种情况吗?

没有。 请改用动态对象

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

 [DataContract] public class SerializableDynamicObject : IDynamicMetaObjectProvider { [DataMember] private IDictionary dynamicProperties = new Dictionary(); #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 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 GetDynamicMemberNames () { var dynObj = (SerializableDynamicObject)this.Value; return dynObj.getDynamicMemberNames(); } } 

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

取自这里

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

 public enum eWhatAmI { ListedObjects, StringArrays, Other } public interface IWhatParmType { eWhatAmI whatAmI { get; set; } } public class MyListVersion : IWhatParmType { public eWhatAmI whatAmI { get; set; } public List whatever { get; set; } public MyListVersion() { whatAmI = eWhatAmI.ListedObjects; whatever = new List(); ... 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" property } private void DoViaArray( MyArrayVersion parm1 ) { .. do whatever based on the "string []" property } 

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