我想创建一个参数(ParameterExpression类的实例),它应该实现多个接口(让它们是IComparable,IFormattable),如下所示:
//TypeWithIComparableIFormattable composite_type = ...;
ParameterExpression parameter = Parameter(composite_type, "composite_param");
// Usage specific methods of composite param from implemented interfaces
答案 0 :(得分:1)
尽管变量/参数可以是不同类型的实例,但您不能像这样对它进行delcare:
IComparable, IFormattable obj;
要进行多界面实施检查,您可以:
Delcare您自己的界面,说IComparableAndFormattable
,继承自IComparable
和IFormattable
。但是这种方法要求参数类型必须实现接口。
执行运行时检查。它很罗嗦,但保持代码保持灵活性:
使用Expression.TypeAs()
方法将参数转换为所需类型。
var param = Expression.Parameter(typeof(object), "o");
// IComparable comparable;
var comparableDeclare = Expression.Parameter(typeof(IComparable), "comparable");
// comparable = o as IComparable;
var comparableAssign = Expression.Assign(comparableDeclare, Expression.TypeAs(param, typeof(IComparable)));
// if (comparable == (IComparable)null)
// {
// throw new ArgumentException("The parameter must be a instance of IComparable.", nameof(o));
// }
var comparableCheck = Expression.IfThen(Expression.Equal(comparableDeclare, Expression.Constant(null, typeof(IComparable))),
ThrowNotTypeOf(typeof(IComparable), param.Name));
var formattableDeclare = Expression.Parameter(typeof(IFormattable), "formattable");
// formattable = o as IFormattable;
var formattableAssign = Expression.Assign(formattableDeclare, Expression.TypeAs(param, typeof(IFormattable)));
// if (formattable == (IFormattable)null)
// {
// throw new ArgumentException("The parameter must be a instance of IFormattable.", nameof(o));
// }
var formattableCheck = Expression.IfThen(
Expression.Equal(formattableDeclare, Expression.Constant(null, typeof(IFormattable))),
ThrowNotTypeOf(typeof(IFormattable), param.Name));
var block = Expression.Block(
new [] {
comparableDeclare, formattableDeclare
}, // local variables
comparableAssign, comparableCheck, formattableAssign, formattableCheck);
foreach (var exp in block.Expressions)
{
Console.WriteLine(exp);
}
// Compile the expression tree
var method = Expression.Lambda<Action<object>>(block, param).Compile();
method.Invoke(new ComparableFormattable());
其中ThrowNotTypeOf
是生成throw new ArgumentException
语句的辅助方法:
private static Expression ThrowNotTypeOf(Type type, string paramName)
{
var ctor = typeof(ArgumentException).GetConstructor(new[] { typeof(string), typeof(string) });
Debug.Assert(ctor != null);
var messageArg = Expression.Constant($"The parameter must be an instance of '{type.Name}'.");
var paramArg = Expression.Constant(paramName);
return Expression.Throw(Expression.New(ctor, messageArg, paramArg));
}