[英]StructureMap | How to create a singleton instance / get always the same instance
我有一个类UserManagement
并且始终希望获得相同的instance
(如单例模式)。 所以我的问题是,现在我总是得到一个名为“ Singleton”的新instance
。 我是StructureMap
新手。 我曾经尝试都版本( http://structuremap.github.io/object-lifecycle/ )( http://structuremap.github.io/glossary/网站上的描述)。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Container container = new Container(new UserManagement());
//UserManagement instance = container.GetInstance<UserManagement>("Singleton");
UserManagement instance = container.GetInstance<UserManagement>();
MessageBox.Show(instance.Test);
}
}
public interface IUser
{
void DoSomethingFancy();
}
public class User : IUser
{
public void DoSomethingFancy()
{
}
}
public interface IDatabase
{
void DoSomething();
}
public class Database : IDatabase
{
public void DoSomething()
{
}
}
public class UserManagement : Registry
{
public string Test;
private Container _Container;
private IUser _User;
private IDatabase _Database;
public UserManagement()
{
_Container = new Container(_ =>
{
_.For<IUser>().Use<User>();
_.For<IDatabase>().Use<Database>();
});
_User = _Container.GetInstance<IUser>();
_Database = _Container.GetInstance<IDatabase>();
Test = DateTime.Now.ToString();
//For<UserManagement>().AddInstances(x =>
//{
// x.Type<UserManagement>().Named("Singleton");
//});
For<UserManagement>().Singleton();
}
}
我的解决方案有3个项目
Bootstrapper
) MainWindow.xaml
) LoginAction
- UserManagement
) public static class Bootstrapper
{
public static Container Container => _Container ?? (_Container = InitializeContainer());
private static Container _Container;
public static Func<Container> InitializeContainer;
}
public partial class App : Application
{
public App()
{
Bootstrapper.InitializeContainer += InitializeContainer;
}
private Container InitializeContainer()
{
Container container = new Container(c => c.Scan(scanner =>
{
scanner.TheCallingAssembly();
scanner.WithDefaultConventions();
scanner.AssembliesFromApplicationBaseDirectory();
}));
container.Configure(c =>
{
c.ForSingletonOf<UserManagement>();
c.For<IUser>().Use<UserAdv>();
}
);
return container;
}
}
<Window x:Class="Gui.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:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:myFramework="clr-namespace:MyFramework;assembly=MyFramework"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Button Content="Button" HorizontalAlignment="Left" Margin="383,228,0,0" VerticalAlignment="Top" Width="75">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<myFramework:LoginAction/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
</Window>
public class LoginAction : TriggerAction<DependencyObject>
{
protected override void Invoke(object parameter)
{
UserManagement userManagement = Bootstrapper.Container.GetInstance<UserManagement>();
Console.WriteLine(userManagement.Test); //Just to see if it's still the same instance who holds for example the current user.
}
}
public interface IUser
{
string Name { get; }
void DoSomethingFancy();
}
public class User : IUser
{
public string Name { get; } = "default";
public void DoSomethingFancy()
{
}
}
public class UserAdv : IUser
{
public string Name { get; } = "Advanced";
public void DoSomethingFancy()
{
}
}
public interface IDatabase
{
void DoSomething();
}
public class Database : IDatabase
{
public void DoSomething()
{
}
}
public class UserManagement
{
public string Test;
public IUser User;
private IDatabase _Database;
public UserManagement(IUser user, IDatabase database)
{
User = user;
_Database = database;
Test = DateTime.Now.ToString();
}
}
如果我理解正确,那么我的主应用程序现在将在application startup
内初始化和配置Container
。 Bootstrapper
类在那里保存一个静态实例。 MyFramework
从静态Container
实例中获取UserManangement
的实例。
这是使用StructureMap
的正确方法吗? 感谢您的耐心等待!
您应该声明:
ForConcreteType<UserManagement>().Singleton();
编辑:
您可以实现引导程序类,并在程序启动期间调用Initialize()
方法:
public sealed class Bootstrapper
{
private static StructureMap.Container _container;
public StructureMap.Container MyContainer
{
get { return _container; }
}
static Bootstrapper()
{
}
public static Initialize()
{
StructureMap.Configuration.DSL.Registry registry = new StructureMap.Configuration.DSL.Registry();
registry.For<IUser>().Use<User>();
registry.For<IDatabase>().Use<Database>();
registry.ForConcreteType<UserManagement>().Singleton();
_container = new Container(registry);
}
}
从UserManagement
类中删除容器初始化,然后让DI框架注入具体的类型/对象。
public class UserManagement
{
public string Test;
private IUser _user;
private IDatabase _database;
public UserManagement(IUser user, IDatabase database)
{
_user = user;
_database = database;
Test = DateTime.Now.ToString();
}
}
修改您的WPF测试窗口:
public partial class MainWindow : Window
{
static MainWindow()
{
// only for demonstration!!!
Bootstrapper.Initialize();
}
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Container container = Bootstrapper.MyContainer;
UserManagement instance = container.GetInstance<UserManagement>();
MessageBox.Show(instance.Test);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.