“参数”和“列表”哪个更好
本文关键字:更好 参数 列表 | 更新日期: 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
}
然后,如果您需要为每个特定的对象实例扩展设置,则可以在特定的子处理程序方法中进行处理,以填充或强制隐含任何默认值。