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

时间:2018-03-27 10:18:23

标签: c# structuremap

我有一个班级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. Gui( WpfApp - MainWindow.xaml
  3. 框架(类库 - LoginAction - UserManagement
  4. BootstrapperLibrary

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

    如果我理解正确,我的主应用程序现在会初始化并配置Container中的application startupBootstrapper类在那里持有一个静态实例。 MyFramework从静态UserManangement实例中提取Container的实例。

    这是如何使用StructureMap的正确方法吗?感谢您的耐心等待!

1 个答案:

答案 0 :(得分:0)

您应该声明:

ForConcreteType<UserManagement>().Singleton();

修改

您可以在程序启动期间实现一个bootstrapper类并调用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);
    }
}