我创建了一个小型便携式库(参考,目标:Windows, Windows 8, Windows Phone 7.5)用于教育目的。我决定在我的小Windows 8 Metro风格的应用程序中使用它。不幸的是,当我从库调用方法时,抛出异常:
应用程序调用了为另一个线程编组的接口。
:
return Activator.CreateInstance(outputType, constructorArguments.ToArray());
(解决方法)outputType是一个类型的(ClassFromMyMetroStyleApp)。库被添加到项目中作为dll引用。
我能做什么来解决这个问题?
编辑:方法是从Metro Style应用程序解决方案中的UnitTest调用的:
[TestClass]
public class ResolvingTypesTests
{
/// <summary>
/// The school context interface test.
/// </summary>
[TestMethod]
public void SchoolContextTest()
{
var schoolContext = TypeService.Services.Resolve<ISchoolContext>();
Assert.AreEqual(typeof(SchoolCollection), schoolContext.GetType());
}
}
其中TypeService是静态类,Services是IResolvable类型的静态属性(接口由库提供)。
服务属性:
/// <summary>
/// The resolvable.
/// </summary>
private static IResolvable resolvable;
/// <summary>
/// Gets the type services.
/// </summary>
public static IResolvable Services
{
get
{
if (resolvable == null)
{
var builder = new ContainerBuilder();
builder.Register();
resolvable = builder.Build();
}
return resolvable;
}
}
当你在一个线程中使用在另一个线程中创建的某些对象(通常是UI对象)时,你可以在单线程公寓中得到这个错误。
找到了解决方案(感谢Hans Passant提供的线索!)需要为测试方法添加一个属性:
[UITestMethod]
不鼓励使用Activator,不仅是因为跨线程访问,还因为性能原因。http://bloggingabout.net/blogs/vagif/archive/2010/04/02/don-t-use-activator-createinstance-or-constructorinfo-invoke-use-compiled-lambda-expressions.aspx
这里作者提供了Activator和使用Lambda表达式实例化对象之间的比较。我将代码包装在u的一个方法中。试试
public object CreateObject(Type type)
{
var ctor = type.GetConstructor(new Type[]{});
// Make a NewExpression that calls the ctor with the args we just created
NewExpression newExp = Expression.New(ctor, null);
// Create a lambda with the New expression as body and our param object[] as arg
LambdaExpression lambda = Expression.Lambda(newExp, null);
// Compile it
var compiled = lambda.Compile();
if (compiled != null)
{
}
return compiled.DynamicInvoke();
}