繁体   English   中英

结构图| 如何创建单例实例/始终获取相同的实例

[英]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个项目

  1. BootstrapperLibrary( 类库 Bootstrapper
  2. 桂( WpfApp - MainWindow.xaml
  3. 框架( 类库 LoginAction - UserManagement

引导程序库

Bootstrapper.cs

public static class Bootstrapper
{
    public static Container Container => _Container ?? (_Container = InitializeContainer());
    private static Container _Container;

    public static Func<Container> InitializeContainer;    
}

App.xaml.cs

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;
    }
}

MainWindow.xaml

<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>

构架

LoginAction.cs

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.
    }
}

UserManagement.cs

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM