C# 将一个或另一个WPF DLL加载到主WPF应用程序中

C# 将一个或另一个WPF DLL加载到主WPF应用程序中,c#,wpf,xaml,dll,C#,Wpf,Xaml,Dll,正在查看加载XAML/events/everything,该DLL连接到用户控件,该DLL在运行时根据配置文件加载到另一个WPF项目中 所以你有两个DLL,只有一个是基于JSON配置加载的,但是我希望我的所有按钮和所有东西都能正常工作。这是我的密码 灰色动态链接库的用户控制 <UserControl x:Class="WPFGreyButtonTest.InstrumentUserControl" xmlns="http://schemas.microsoft.c

正在查看加载XAML/events/everything,该DLL连接到用户控件,该DLL在运行时根据配置文件加载到另一个WPF项目中

所以你有两个DLL,只有一个是基于JSON配置加载的,但是我希望我的所有按钮和所有东西都能正常工作。这是我的密码

灰色动态链接库的用户控制

<UserControl x:Class="WPFGreyButtonTest.InstrumentUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WPFGreyButtonTest"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Label x:Name="colourName" Content="GREY" HorizontalAlignment="Left" Height="93" Margin="284,88,0,0" VerticalAlignment="Top" Width="243" FontWeight="Bold" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontSize="50" Foreground="#FF8B8B8B"/>
    </Grid>
</UserControl>

没有实际代码

紫色DLL的用户控件

<UserControl x:Class="WPFPurpleButtonTest.InstrumentUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WPFPurpleButtonTest"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Label x:Name="colourName" Content="PURPLE" HorizontalAlignment="Left" Height="93" Margin="284,88,0,0" VerticalAlignment="Top" Width="243" FontWeight="Bold" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontSize="50" Foreground="#FFDC00FF"/>
        <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="365,253,0,0" VerticalAlignment="Top" Width="75"/>

    </Grid>
</UserControl>

代码(两个DLL具有相同的类名,即InstrumentUserControl)

使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
命名空间WPFPurpleButtonTest
{
/// 
///InstrumentUserControl.xaml的交互逻辑
/// 
公共部分类InstrumentUserControl:UserControl
{
公共静态只读DependencyProperty InnerButtonProperty=DependencyProperty.Register(“InnerButton”、typeof(Button)、typeof(InstrumentUserControl));
公共按钮内部按钮
{
获取{return(Button)GetValue(InnerButtonProperty);}
set{SetValue(InnerButtonProperty,value);}
}
公共工具用户控制()
{
初始化组件();
InnerButton=按钮;
}
}
}
主WPF应用程序代码

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPFSandBox
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        UserControl userControl = null;
        InstrumentEnum instrumentType = InstrumentEnum.Invalid;
        string dllToLoad = null;

        // When we first initialize our WPF app, in the constructor we can
        // allow a config file (such as a json) to be read and load up
        // an appropriate user control view
        public MainWindow()
        {
            InitializeComponent();
            ReadJson();
            LoadRunTimeDLL();

            //var ucs = new List<InstrumentUserControl>();
            var ucs = new List<UserControl>();

            ucs.Add(userControl);
            //ucs.Add(new UserControl1());
            //ucs.Add(new UserControl1());
            //ucs.Add(new UserControl1());

            ic.ItemsSource = ucs;
        }

        private void ReadJson()
        {
            using (StreamReader r = new StreamReader("../../Config/Config.json"))
            {
                string json = r.ReadToEnd();
                var jsonData = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);

                foreach (var entry in jsonData)
                {
                    if (entry.Key == "InstrumentType")
                    {
                        Enum.TryParse(entry.Value, out instrumentType);
                    }
                    else if (entry.Key == "DllToLoad")
                    {
                        dllToLoad = entry.Value;
                    }
                }
            }
        }

        private void LoadRunTimeDLL()
        {
            string assemblyName = string.Format("{0}\\{1}.dll", 
                new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName, dllToLoad);

            if (assemblyName != null)
            {
                Assembly asm = Assembly.LoadFile(assemblyName);
                Type[] tlist = asm.GetTypes();
                foreach (Type t in tlist)
                {
                    if (t.Name == "InstrumentUserControl")
                    {
                        userControl = Activator.CreateInstance(t) as UserControl;
                        break;
                    }
                }

                if (userControl != null)
                {
                    //contentControl.Content = userControl;
                }
            }
        }
    }
}
使用Newtonsoft.Json;
使用Newtonsoft.Json.Linq;
使用制度;
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
运用系统反思;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
命名空间WPFSandBox
{
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
UserControl UserControl=null;
InstrumentEnum instrumentType=InstrumentEnum.无效;
字符串dllToLoad=null;
//当我们第一次初始化WPF应用程序时,在构造函数中我们可以
//允许读取和加载配置文件(如json)
//适当的用户控件视图
公共主窗口()
{
初始化组件();
ReadJson();
LoadRunTimeDLL();
//var ucs=新列表();
var ucs=新列表();
添加(用户控制);
//添加(新的UserControl1());
//添加(新的UserControl1());
//添加(新的UserControl1());
ic.ItemsSource=ucs;
}
私有void ReadJson()
{
使用(StreamReader r=newstreamreader(“../../Config/Config.json”))
{
字符串json=r.ReadToEnd();
var jsonData=JsonConvert.DeserializeObject(json);
foreach(jsonData中的var条目)
{
如果(entry.Key==“InstrumentType”)
{
Enum.TryParse(entry.Value,out instrumentType);
}
else if(entry.Key==“dlltoad”)
{
dllToLoad=输入值;
}
}
}
}
私有void LoadRunTimeDLL()
{
string assemblyName=string.Format(“{0}\\{1}.dll”,
新文件信息(Assembly.getExecutionGassembly().Location).DirectoryName,dllToLoad);
if(assemblyName!=null)
{
Assembly asm=Assembly.LoadFile(assemblyName);
类型[]tlist=asm.GetTypes();
foreach(t列表中的类型t)
{
if(t.Name==“InstrumentUserControl”)
{
userControl=Activator.CreateInstance(t)作为userControl;
打破
}
}
if(userControl!=null)
{
//contentControl.Content=userControl;
}
}
}
}
}
这是主窗口xaml

<Window x:Class="WPFSandBox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPFSandBox"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <!--<Grid>
        <ContentControl Grid.Row="1" x:Name="contentControl" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"/>
    </Grid>-->
    <ItemsControl x:Name="ic" />
</Window>

任何帮助将不胜感激,我如何才能确保无论哪个DLL得到加载,按钮工作正常


我正在尝试在运行时加载WPF DLL。工作正常,但按钮和事件绑定到主WPF应用程序是我不知道如何做的

好的,假设您当前有此设置:

Solution: MainApp
- Project: MainApp (WPF App) 
- Project: PurpleButton (Class Library) 
- Project: GreyButton (Class Library) 
我所说的是添加另一个项目,如下所示:

Solution: MainApp
- Project: MainApp (WPF App) 
- Project: MainAppPlugins (Class Library) <-----
- Project: WPFPurpleButtonTest (Class Library) 
- Project: WPFGreyButtonTest (Class Library) 
using System;
using System.Windows.Controls;

namespace MainAppPlugins
{
    public abstract class PluginButton : UserControl
    {
        public event EventHandler OnProcessedSomeData;
    }
}
然后更新所有其他项目(MainApp、WPFPurpleButtonTest和WPFGreyButtonTest),并向MainAppPlugins添加项目引用(以便每个项目都知道什么是“MainAppPlugins.PluginButton”)

在紫色和灰色中,将用户控件更改为从MainAppPlugins.PluginButton扩展,而不是从UserControl扩展。所以你在两个地方做这个。首先,在代码隐藏中(在.cs文件中):

…在创建控件时,您还可以使用更具体的通用插件按钮类型:

 // userControl = Activator.CreateInstance(t) as UserControl;
 userControl = Activator.CreateInstance(t) as MainAppPlugins.PluginButton;
…这意味着MainApp代码现在可以引用所有常见事件/代码,例如我们的自定义OnProcessedSomeData事件:

userControl.OnProcessedSomeData+=…此处是您的事件处理程序

因此,灰色和紫色按钮可能有90%不同的代码,但其他10%由事件、属性等定义在PluginButton中可以找到任何代码、事件和属性。因为MainApp知道
namespace WPFGreyButtonTest
{
    public partial class InstrumentUserControl : PluginButton // <-- 
    {
      ...your existing code...
    }
}
<mainappplugins:PluginButton x:Class="WPFGreyButtonTest.InstrumentUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:mainappplugins="clr-namespace:MainAppPlugins;assembly=MainAppPlugins"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:WPFGreyButtonTest"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">
...
</mainappplugins:PluginButton>
// if (t.Name == "InstrumentUserControl")
if(t.BaseType == typeof(MainAppPlugins.PluginButton))
{
   ...
}
 // userControl = Activator.CreateInstance(t) as UserControl;
 userControl = Activator.CreateInstance(t) as MainAppPlugins.PluginButton;
public abstract class PluginButton : UserControl
{
    ...

    public virtual string GetData()
    {
        return "Default value";
    }
}
namespace WPFGreyButtonTest
{
    public partial class InstrumentUserControl : PluginButton 
    {
        ...your existing code...

        public override string GetData()
        {
            return "Data from the Grey button";
        }
    }
}
namespace WPFPurpleButtonTest
{
    public partial class InstrumentUserControl : PluginButton 
    {
        ...your existing code...

        public override string GetData()
        {
            return "Data from the Purple button";
        }
    }
}