.net 为什么变量的泛型类型参数必须与设置它的相应OutArgument精确匹配?
考虑以下C代码:.net 为什么变量的泛型类型参数必须与设置它的相应OutArgument精确匹配?,.net,workflow-foundation,.net,Workflow Foundation,考虑以下C代码: public static Foo CreateFoo() { return new Foo(); } // ... public static void Main() { IFoo foo = CreateFoo(); } 相当简单:赋值语句允许目标变量的类型不如表达式的类型具体 因此,我期望注释掉的行能够工作,但由于以下原因,它失败了,迫使任何设置Foo的东西返回具体Foo类的实例,而不仅仅是IFoo: 子活动定义 我想有一个变通方法可以让它看起来像这
public static Foo CreateFoo()
{
return new Foo();
}
// ...
public static void Main()
{
IFoo foo = CreateFoo();
}
相当简单:赋值语句允许目标变量的类型不如表达式的类型具体
因此,我期望注释掉的行能够工作,但由于以下原因,它失败了,迫使任何设置Foo的东西返回具体Foo类的实例,而不仅仅是IFoo:
子活动定义
我想有一个变通方法可以让它看起来像这样:
public static void Run()
{
IFoo foo;
Foo uglyWorkaround = TryExistingActivity();
if (uglyWorkaround == null)
{
foo = UseMyShinyNewActivity();
}
else
{
foo = uglyWorkaround;
}
}
…这可能就是我最终要做的,尽管我倾向于遵循传统的东西并使用它,作为使单元测试不会失败的魔杖
总结
从根本上说,为什么我不能使用变量来存储活动的OutArgument的结果?或者这仅仅是标准的实施成本与效益之比
编辑1:完全用C语言复制
这使用了上面子活动定义中的相同活动
class Program
{
static void Main()
{
Variable<IFoo> theFoo = new Variable<IFoo>("TheFoo");
Sequence sequence = new Sequence
{
Variables =
{
theFoo
},
Activities =
{
new ActivityWithOutArgument
{
Result = theFoo
}
}
};
// The following fails with:
// InvalidWorkflowException was Unhandled
// The following errors were encountered while processing the workflow tree:
// 'VariableReference<Foo>': Variable 'System.Activities.Variable`1[MyNamespace.IFoo]' cannot be used
// in an expression of type 'MyNamespace.Foo', since it is of type 'MyNamespace.IFoo' which is not compatible.
WorkflowInvoker.Invoke(sequence);
}
}
由于WF的设计方式,输入和输出由泛型类表示,而泛型类不能是协变或逆变的 但是,WF的任何基本要素都不能阻止这一点,因此这是可行的: 使用制度; 使用系统活动; 使用系统、活动、报表; 使用系统、活动、表达式; 命名空间WorkflowConsoleApplication1 { 公共接口IFoo { 虚无点滴; } 公开密封等级Foo:IFoo { public void DoThing=>Console.WriteLineHello; } 不带参数的公共密封类活动:CodeActivity { 受保护的覆盖Foo ExecuteCodeActivityContext=>new Foo; } 内部静态类程序 { 专用静态空干管 { 变量theFoo=新变量name of foo; 序列=新序列 { 变数= { theFoo, }, 活动= { 新分配 { To=theFoo, 值=新类型 { 操作数=不带参数的新活动, }, }, 新方法 { TargetObject=新的InArgumenttheFoo, MethodName=nameofIFoo.DoThing, }, } }; WorkflowInvoker.Invokesequence; } } }
这是一个完全可以用C代码重现的问题吗?@BenAaronson是-请参见编辑1。这个问题的顶部答案是否涵盖了它@不,这只是处理标准的C/.NET类型转换规则。我在这里的基本问题是工作流基础,即编程模型,有它自己的一组独立的关于什么可以被分配给变量的规则,在这种情况下,它与正常的C/Net编程模型中的同类事物混淆不一致。
public static void Run()
{
IFoo foo = TryExistingActivity();
if (foo == null)
{
foo = UseMyShinyNewActivity();
}
}
public static void Run()
{
IFoo foo;
Foo uglyWorkaround = TryExistingActivity();
if (uglyWorkaround == null)
{
foo = UseMyShinyNewActivity();
}
else
{
foo = uglyWorkaround;
}
}
class Program
{
static void Main()
{
Variable<IFoo> theFoo = new Variable<IFoo>("TheFoo");
Sequence sequence = new Sequence
{
Variables =
{
theFoo
},
Activities =
{
new ActivityWithOutArgument
{
Result = theFoo
}
}
};
// The following fails with:
// InvalidWorkflowException was Unhandled
// The following errors were encountered while processing the workflow tree:
// 'VariableReference<Foo>': Variable 'System.Activities.Variable`1[MyNamespace.IFoo]' cannot be used
// in an expression of type 'MyNamespace.Foo', since it is of type 'MyNamespace.IFoo' which is not compatible.
WorkflowInvoker.Invoke(sequence);
}
}