c# - 将属于动态加载的 dll 的类强制转换为属于另一个 dll 的抽象类
问题描述
我在从外部程序集中使用抽象类强制转换 ViewModel 类时遇到问题。
我有 2 个 dll 和一个可执行文件:
一个抽象类到dll Cockpit.RUN.Common.dll中,这个Dll被引用:在dll Cockpit.RUN.ViewModels的另一个项目和可执行Cockpit.RUN.Test的项目中,但是没有引用Cocpit.RUN.ViewModels在可执行的项目中,因为它是动态加载的
抽象类:(dll)
using Caliburn.Micro;
namespace Cockpit.RUN.Common
{
public abstract class PluginModel : PropertyChangedBase
{
public abstract double Width { get; set; }
public abstract double Height { get; set; }
public abstract double Left { get; set; }
public abstract double Top { get; set; }
private double zoomfactorfrompluginmodel;
public double ZoomFactorFromPluginModel
{
get => zoomfactorfrompluginmodel;
set
{
zoomfactorfrompluginmodel = value;
NotifyOfPropertyChange(() => ZoomFactorFromPluginModel);
}
}
public string NameUC;
}
}
第二个包含 viewmodels Cockpit.RUN.ViewModels.dll 的 dll 我在这个 dll 中有很多不同的插件:Push_ViewModel、Switch_ViewModel....
我用抽象类派生每个类,例如 Push_ViewModel:
using Cockpit.RUN.Common;
using System.Windows;
using System.Windows.Input;
namespace Cockpit.RUN.ViewModels
{
public class PushButton_ViewModel : PluginModel
{
public PushButton_ViewModel(params object[] settings)
{
NameUC = (string)settings[2];
Layout = new LayoutPropertyViewModel();
}
public override double Left
{
get => Layout.UCLeft;
set => Layout.UCLeft = value;
}
public override double Top
{
get => Layout.UCTop;
set => Layout.UCTop = value;
}
public override double Width
{
get => Layout.Width;
set => Layout.Width = value;
}
public override double Height
{
get => Layout.Height;
set => Layout.Height = value;
}
}
}
再说一件事,这个插件 dll 在引导程序期间动态加载
protected override IEnumerable<Assembly> SelectAssemblies()
{
var assemblies = new List<Assembly>();
assemblies.AddRange(base.SelectAssemblies());
assemblies.Add(Assembly.LoadFile(@"J:\ProjetC#\Cockpit-master\Cockpit.RUN.Test\bin\Debug\Cockpit.RUN.ViewModels.dll"));
assemblies.Add(Assembly.LoadFile(@"J:\ProjetC#\Cockpit-master\Cockpit.RUN.Test\bin\Debug\Cockpit.RUN.Views.dll"));
return assemblies;
}
所以问题是当我想用抽象基础 PulginModel 转换每个 ViewModel 时,我的结果为空:
using Cockpit.RUN.Common;
:
:
public BindableCollection<PluginModel> MyCockpitPlugins { get; set; }
:
:
model = "Cockpit.RUN.ViewModels.PushButton_ViewModel, Cockpit.RUN.ViewModels";
var typeClass = Type.GetType(model); // its ok
var viewmodel = resolutionRoot.TryGet(typeClass, param); // Its ok i have an instance of PushButton_ViewModel
var v = viewmodel as PluginModel; //-> not ok its null
var w = (PluginModel)viewmodel; //-> not ok its error
// So i cant display my list of views associated
MyCockpitPlugins.Add(v);
我做错了什么吗?
在强制转换之前在中断调试时加载的程序集:
以及 typeof 和 GetType 的结果:
typeof(PluginModel) gives {Name = "PluginModel" FullName = "Cockpit.RUN.Common.PluginModel"}
viewmodel.GetType().BaseType gives {Name = "PluginModel" FullName = "Cockpit.RUN.ViewModels.PluginModel"}
解决方案
接口(dll):
public interface IPlugin
{
ICallbacks Callbacks { get; set; }
string NameUC { get; set; }
double Width { get; set; }
double Height { get; set; }
double Left { get; set; }
double Top { get; set; }
double ZoomFactorFromPluginModel { get; set; }
}
public interface ICallbacks
{
void SomeCallback();
}
您的实施:
public class PushButton_ViewModel : PluginModel, IPlugin
{
// How was this going to work? Who makes the instance?
//public PushButton_ViewModel(params object[] settings)
//{
// NameUC = (string)settings[2];
// Layout = new LayoutPropertyViewModel();
//}
public ICallbacks Callbacks { get; set; }
public override double Left
{
get => Layout.UCLeft;
set => Layout.UCLeft = value;
}
public override double Top
{
get => Layout.UCTop;
set => Layout.UCTop = value;
}
public override double Width
{
get => Layout.Width;
set => Layout.Width = value;
}
public override double Height
{
get => Layout.Height;
set => Layout.Height = value;
}
}
然后初始化它
Type t = Type.GetType("PushButton_ViewModel");
object obj = FormatterServices.GetUninitializedObject(t);
IPlugin instance = obj as IPlugin;
instance.NameUC = "the name";
instance.Callbacks = new CallbacksModel();
推荐阅读
- spring-boot - 如何在 graphql-spring-boot-autoconfigure 中跳过/禁用 GraphQLExtendedScalarsInitializer
- azure-data-factory - Azure 数据工厂重新启动单个群集
- java - 如何发布列表
在改造的参数中? - task - STM32 FreeRTOS,如何清除任务信号标志
- graphql - 从 .graphql 文件导出多个查询
- javascript - JSDoc @param 作为预定义的常量对象
- sql-server - 是否有旧版本的声明中的 var 分配不起作用?
- google-bigquery - BigQuery:为什么当我尝试执行查询时给我错误 Not found: Dataset was not found in location US
- geoserver - 在 Geoserver 2.15.1 中加载 sld 栅格样式时出现问题
- mysql - 性能最佳的 MySQL 搜索文本