无法将 'MS.Internal.Controls.AddInHost' 转换回类型 'System.Windows.Controls.UserControl' 或将其转换为我的自定义界面
Unable to convert 'MS.Internal.Controls.AddInHost' back to type 'System.Windows.Controls.UserControl' or cast it to my custom interface
我已将用户控件实例创建到单独的应用程序域中,并根据插件框架指南将其转换为 INativeHandleContract,并且我能够将框架实例的引用传递到主机应用程序域中。当我在主机应用程序应用程序域中将 INativeHandleContract 转换回 UIElement 时,我无法将 UIElement 转换为我的自定义接口类型。
谁能告诉我是否可以将 Framework 元素转换为 userControl 或将其转换为我的自定义界面?
这是代码的一部分:
public INativeHandleContract GetControl(string AssemblyName, string strFullNamespaceName)
{
var assembly = Assembly.LoadFrom(m_strAssemblyDirectory + AssemblyName);
var type1 = typeof(IUPiAssemblyProcedure);
var type2 = typeof(IUPiCardProcedure);
var type3 = typeof(IUPiDatabaseFrame);
var type4 = typeof(IUPiUserFrame);
var t = from T in assembly.GetTypes() where type1.IsAssignableFrom(T) || type2.IsAssignableFrom(T) || type3.IsAssignableFrom(T) || type4.IsAssignableFrom(T) select T;
if (t.Count<Type>() == 0) return null;
var tName = t.First<Type>().FullName;
return FrameworkElementAdapters.ViewToContractAdapter((FrameworkElement)assembly.CreateInstance(tName));
}
public void LoadUserControl(INativeHandleContract contract)
{
var uControl = FrameworkElementAdapters.ContractToViewAdapter(contract);
var t = uControl.GetType();
t.GetMethod("methodName");
...
}
我的目标是调用自定义接口中定义的一些方法,由我加载的程序集中的一种类型实现。
问候
蒂霍米尔·布拉戈耶夫
我找到了解决办法!正如所描述的 here、"Because the host application gets an HwndHost, the host application cannot convert the object that is returned by ContractToViewAdapter to the type it is implemented as by the add-in (for example, a UserControl)."
因此,如果我想访问我的子域中的类型实例,我必须通过我的代理来完成:
public class Main
{
private AppDomain ad = null;
private proxy remoteWorker = null;
public INativeHandleContract LoadAssembly(string assemblyname, string fullInterfaceName)
{
if (ad != null)
{
AppDomain.Unload(ad);
}
var domSetup = new AppDomainSetup();
domSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
domSetup.PrivateBinPath = AppDomain.CurrentDomain.BaseDirectory;
domSetup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
domSetup.LoaderOptimization = LoaderOptimization.MultiDomainHost;
var adevidence = AppDomain.CurrentDomain.Evidence;
ad = AppDomain.CreateDomain(assemblyname, adevidence, domSetup);
ad.AssemblyResolve += ad_AssemblyResolve;
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
remoteWorker = (proxy)ad.CreateInstanceAndUnwrap(typeof(proxy).Assembly.FullName, "INATO.UPINAIS.UCLibrary.proxy");
return remoteWorker.GetControl(assemblyname, fullInterfaceName);
}
public void DoTheTrick()
{
var uControl = LoadAssembly("assemblyName", "interfaceName");
panel.Content = FrameworkElementAdapters.ContractToViewAdapter(uControl);
remoteWorker.RemoteInvoke("methodName", new object[] { });
}
}
public class proxy : MarshalByRefObject
{
private object _currentInstance;
public INativeHandleContract GetControl(string AssemblyName, string strFullNamespaceName)
{
var assembly = Assembly.LoadFrom(m_strAssemblyDirectory + AssemblyName);
var type1 = typeof(IUPiAssemblyProcedure);
var type2 = typeof(IUPiCardProcedure);
var type3 = typeof(IUPiDatabaseFrame);
var type4 = typeof(IUPiUserFrame);
var t = from T in assembly.GetTypes() where type1.IsAssignableFrom(T) || type2.IsAssignableFrom(T) || type3.IsAssignableFrom(T) || type4.IsAssignableFrom(T) select T;
if (t.Count<Type>() == 0) return null;
var tName = t.First<Type>().FullName;
_currentInstance = assembly.CreateInstance(tName);
return FrameworkElementAdapters.ViewToContractAdapter((FrameworkElement)_currentInstance);
}
public void RemoteInvoke(string methodName, object[] parameters)
{
var type = _currentInstance.GetType();
var mi = type.GetMethod(methodName);
mi.Invoke(_currentInstance, parameters);
}
}
我已将用户控件实例创建到单独的应用程序域中,并根据插件框架指南将其转换为 INativeHandleContract,并且我能够将框架实例的引用传递到主机应用程序域中。当我在主机应用程序应用程序域中将 INativeHandleContract 转换回 UIElement 时,我无法将 UIElement 转换为我的自定义接口类型。
谁能告诉我是否可以将 Framework 元素转换为 userControl 或将其转换为我的自定义界面?
这是代码的一部分:
public INativeHandleContract GetControl(string AssemblyName, string strFullNamespaceName)
{
var assembly = Assembly.LoadFrom(m_strAssemblyDirectory + AssemblyName);
var type1 = typeof(IUPiAssemblyProcedure);
var type2 = typeof(IUPiCardProcedure);
var type3 = typeof(IUPiDatabaseFrame);
var type4 = typeof(IUPiUserFrame);
var t = from T in assembly.GetTypes() where type1.IsAssignableFrom(T) || type2.IsAssignableFrom(T) || type3.IsAssignableFrom(T) || type4.IsAssignableFrom(T) select T;
if (t.Count<Type>() == 0) return null;
var tName = t.First<Type>().FullName;
return FrameworkElementAdapters.ViewToContractAdapter((FrameworkElement)assembly.CreateInstance(tName));
}
public void LoadUserControl(INativeHandleContract contract)
{
var uControl = FrameworkElementAdapters.ContractToViewAdapter(contract);
var t = uControl.GetType();
t.GetMethod("methodName");
...
}
我的目标是调用自定义接口中定义的一些方法,由我加载的程序集中的一种类型实现。
问候 蒂霍米尔·布拉戈耶夫
我找到了解决办法!正如所描述的 here、"Because the host application gets an HwndHost, the host application cannot convert the object that is returned by ContractToViewAdapter to the type it is implemented as by the add-in (for example, a UserControl)."
因此,如果我想访问我的子域中的类型实例,我必须通过我的代理来完成:
public class Main
{
private AppDomain ad = null;
private proxy remoteWorker = null;
public INativeHandleContract LoadAssembly(string assemblyname, string fullInterfaceName)
{
if (ad != null)
{
AppDomain.Unload(ad);
}
var domSetup = new AppDomainSetup();
domSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
domSetup.PrivateBinPath = AppDomain.CurrentDomain.BaseDirectory;
domSetup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
domSetup.LoaderOptimization = LoaderOptimization.MultiDomainHost;
var adevidence = AppDomain.CurrentDomain.Evidence;
ad = AppDomain.CreateDomain(assemblyname, adevidence, domSetup);
ad.AssemblyResolve += ad_AssemblyResolve;
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
remoteWorker = (proxy)ad.CreateInstanceAndUnwrap(typeof(proxy).Assembly.FullName, "INATO.UPINAIS.UCLibrary.proxy");
return remoteWorker.GetControl(assemblyname, fullInterfaceName);
}
public void DoTheTrick()
{
var uControl = LoadAssembly("assemblyName", "interfaceName");
panel.Content = FrameworkElementAdapters.ContractToViewAdapter(uControl);
remoteWorker.RemoteInvoke("methodName", new object[] { });
}
}
public class proxy : MarshalByRefObject
{
private object _currentInstance;
public INativeHandleContract GetControl(string AssemblyName, string strFullNamespaceName)
{
var assembly = Assembly.LoadFrom(m_strAssemblyDirectory + AssemblyName);
var type1 = typeof(IUPiAssemblyProcedure);
var type2 = typeof(IUPiCardProcedure);
var type3 = typeof(IUPiDatabaseFrame);
var type4 = typeof(IUPiUserFrame);
var t = from T in assembly.GetTypes() where type1.IsAssignableFrom(T) || type2.IsAssignableFrom(T) || type3.IsAssignableFrom(T) || type4.IsAssignableFrom(T) select T;
if (t.Count<Type>() == 0) return null;
var tName = t.First<Type>().FullName;
_currentInstance = assembly.CreateInstance(tName);
return FrameworkElementAdapters.ViewToContractAdapter((FrameworkElement)_currentInstance);
}
public void RemoteInvoke(string methodName, object[] parameters)
{
var type = _currentInstance.GetType();
var mi = type.GetMethod(methodName);
mi.Invoke(_currentInstance, parameters);
}
}