我当前的代码如下,它是作为客户端代理公开的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中引入的新内容还有更好的方法来处理这种情况吗?
答案 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();
}
}
一个警告,动态成员可以是任何东西,这意味着在运行时有人可以将方法分配给其中一个字段。如果在您的应用程序中可以实现,则需要确保分配给动态类型的任何方法都不是序列化的。我将此作为练习留给读者。
答案 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
}
然后,如果您需要扩展每个特定对象实例的设置,您可以在特定的子处理程序方法中处理,以填充或强制隐含默认值。