简单来说,就是我有个项目是lib库,此时我想要在其他的项目实现对这个库项目的引用,以实现复用的目的。参考原文,咨询了原作者,源码已经丢失,按照文中的方法已经不能完全复现想要的功能。
01
首先创建一个WPF用户控件库项目命名为mycontrol,在项目里新建用户控件timererViewModel,再在项目里建一个窗体TestView。项目结构如下:
02
然后创建一个WPF应用项目,命名为WpfApp3。新建窗体StartView.xaml,项目结构如下:
其中MyBootstrapper代码如下
using Caliburn.Micro;
using materialtest.ViewModel;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows;
using WpfApp3.ViewModels;
namespace WpfApp3
{
class MyBootstrapper : BootstrapperBase
{
public MyBootstrapper()
{
Initialize();//初始化框架
}
//[Import]
//public MefTestParts mefTestParts { get; set; }
protected override void OnStartup(object sender, StartupEventArgs e)
{
DisplayRootViewFor<StartViewModel>();//显示界面
}
/// <summary>
/// 方法1
/// </summary>
//protected void Configure0()
//{
// var envirmentPath = System.IO.Directory.GetCurrentDirectory();
// //AssemblyCatalog 目录的一种,表示在程序集中搜索
// var assemblyCatalog = new AssemblyCatalog(typeof(StartViewModel).Assembly);//此处这一句实际上没啥用,因为此程序集下没有任何我们需要的实例(各种handler)
// //在某个目录下的dll中搜索。
// //var directoryCatalog = new DirectoryCatalog(@"C:\Program Files (x86)\YWTK\TOOLS\PLUGIN-LIBS\MISC\I12\", "*.dll");
// var directoryCatalog = new DirectoryCatalog(envirmentPath, @"materialtest.dll");
// var aggregateCatalog = new AggregateCatalog(assemblyCatalog, directoryCatalog);
// //创建搜索到的部件,放到容器中。
// container = new CompositionContainer(aggregateCatalog);
// var batch = new CompositionBatch(); //如果还有自己的部件都加在这个地方
// batch.AddExportedValue<IWindowManager>(new WindowManager());
// batch.AddExportedValue<IEventAggregator>(new EventAggregator());
// batch.AddExportedValue(container);
// this.container.Compose(batch);
//}
private SimpleContainer container;
/// <summary>
/// 方法2
/// </summary>
protected override void Configure()
{
var envirmentPath = System.IO.Directory.GetCurrentDirectory();
AssemblySource.Instance.Add(Assembly.LoadFile(Path.Combine(envirmentPath, @"mycontrol.dll")));
//var catalog = new AggregateCatalog(
// AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>());
container = new SimpleContainer();
container.Singleton<SimpleContainer>();
container.Singleton<IWindowManager, WindowManager>();
container.Singleton<IEventAggregator, EventAggregator>();
foreach (var assembly in SelectAssemblies())
{
assembly.GetTypes()
.Where(type => type.IsClass)
.Where(type => type.Name.EndsWith("ViewModel"))
.ToList()
.ForEach(viewModelType => container.RegisterPerRequest(
viewModelType, viewModelType.ToString(), viewModelType));
}
ExternalLoad();
}
private void ExternalLoad()
{
var asmPath = Assembly.GetAssembly(typeof(MyBootstrapper)).Location;
var path = Directory.GetParent(asmPath).FullName;
string filePath = Path.Combine(path, "mycontrol.dll");
var assembly = Assembly.LoadFile(filePath);
assembly.GetTypes()
.Where(type => type.IsClass)
.Where(type => type.Name.EndsWith("ViewModel"))
.ToList()
.ForEach(viewModelType => container.RegisterPerRequest(
viewModelType, viewModelType.ToString(), viewModelType));
}
protected override object GetInstance(Type service, string key)
{
return container.GetInstance(service, key);
}
private readonly SimpleContainer scontainer = new SimpleContainer();
protected override IEnumerable<object> GetAllInstances(Type service)
{
return container.GetAllInstances(service);
}
protected override void BuildUp(object instance)
{
container.BuildUp(instance);
}
protected override void OnExit(object sender, EventArgs e)
{
base.OnExit(sender, e);
this.Application.Shutdown();
}
}
}
其中核心代码为:
var asmPath = Assembly.GetAssembly(typeof(MyBootstrapper)).Location;
var path = Directory.GetParent(asmPath).FullName;
string filePath = Path.Combine(path, "mycontrol.dll");
var assembly = Assembly.LoadFile(filePath);
//如果运行目录不存在mycontrol.dll,则需要将相应的mycontrol.dll拷贝到运行目录里去
其中StartView.xaml代码如下:
<Window
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:WpfApp3.Views"
xmlns:cal="http://www.caliburnproject.org"
xmlns:mycontrol="clr-namespace:mycontrol;assembly=mycontrol" x:Class="WpfApp3.Views.StartView"
mc:Ignorable="d"
Title="StartView" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<ContentControl Margin="2" cal:View.Model="{Binding Timerview}"/>
<GroupBox x:Name="g" Grid.Row="1" MouseLeftButtonDown="g_MouseLeftButtonDown">
<StackPanel Orientation="Horizontal">
<CheckBox x:Name="a"/>
<CheckBox x:Name="b"/>
<CheckBox x:Name="c"/>
<CheckBox x:Name="d"/>
<ContentControl x:Name="ActiveItem"/>
</StackPanel>
</GroupBox>
<GridSplitter Height="3" Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Background="Red"/>
<Button x:Name="open" Content="openwindow" Grid.Row="2" MouseDoubleClick="open_MouseDoubleClick" HorizontalAlignment="Left" VerticalAlignment="Top"/>
</Grid>
</Window>
其中StartViewModel.cs代码如下:
using Caliburn.Micro;
using materialtest.ViewModel;
using materialtest.Views;
using mycontrol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WpfApp3.ViewModels
{
public class StartViewModel:Conductor<object>.Collection.OneActive
{
public timererViewModel Timerview { get; set; }
public StartViewModel()
{
Timerview = IoC.Get<timererViewModel>();
Timerview = new timererViewModel("hello world");
Timerview.Deactivated += Timerview_Deactivated;
Timerview.AttemptingDeactivation += Timerview_AttemptingDeactivation;
Timerview.Activated += Timerview_Activated;
Timerview.ViewAttached += Timerview_ViewAttached;
Timerview.ViewAttached += Timerview_ViewAttached1;
ActivateItem(IoC.Get<timererViewModel>());
}
private void Timerview_ViewAttached1(object sender, ViewAttachedEventArgs e)
{
}
private void Timerview_ViewAttached(object sender, ViewAttachedEventArgs e)
{
}
private void Timerview_Activated(object sender, ActivationEventArgs e)
{
throw new NotImplementedException();
}
private void Timerview_AttemptingDeactivation(object sender, DeactivationEventArgs e)
{
throw new NotImplementedException();
}
private void Timerview_Deactivated(object sender, DeactivationEventArgs e)
{
throw new NotImplementedException();
}
public void open()
{
Timerview.change();
var winManager =IoC.Get<IWindowManager>();
var test=IoC.Get<TestViewModel>();
var test1=new TestViewModel("都不是啥好人");
winManager.ShowDialog(test1);
Console.WriteLine(test1.mzr);
}
}
}
这样其它项目的界面就成功的被加载到了我们的主项目中,这样如果我们定义了公共的接口,直接导出接口类型,就很好地实现了主项目和子项目的解耦。
想要免费源码可以私信