“参数”和“列表”哪个更好

本文关键字:更好 参数 列表 | 更新日期: 2023-09-27 18:00:35

我当前的代码如下,它是一个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中引入的新内容,是否还有更好的方法来处理这种情况?

“参数”和“列表”哪个更好

使用动态对象代替

要创建一个使用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();
}
}

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

取自此处

是否可以允许"接口"参数。由此,您可以根据接口值设置处理多个事情。只是射出一个简单的样本。

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
}

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