第二次创建实例时,它会从容器中获得相同的瞬态实例

问题描述

我正在尝试通过遵循MVVM模式并使用控制反转来开发WPF应用程序。 我正在使用简单注入器作为IoC容器。

我必须为DbContext实现类似于Ambient Scope的东西。基本上,每次我需要调用与数据交互的服务方法时,都会释放它的新UoW实例,并且该实例将在所有实例中使用。实现数据库操作的数据服务。

像这样的东西:

// Example of Service method 

[STAThread]
static void Main()
{
    _container = Bootstrap();
    Debug.WriteLine(CultureInfo.CurrentCulture);

    Thread.CurrentThread.CurrentCulture = new CultureInfo("en-Us");
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");

   
    _app = new App();
    _app.InitializeComponent();

    var mainWindow = _container.GetInstance<MainWindow>();
    mainWindow.Closed += MainWindow_Closed;
    _app.Run(mainWindow);
}

public partial class MainWindow : Window
{
    public MainWindow(MainWindowviewmodel viewmodel)
    {
        InitializeComponent();

        DataContext = viewmodel;
    }
}
<Window x:Class="WpfRaddispenser.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:userControls="clr-namespace:WpfRaddispenser.UserControls"
        xmlns:vm="clr-namespace:WpfRaddispenser.viewmodel"
        mc:Ignorable="d"
        Title="WpfRaddispenser" Height="768" Width="1024" 
        d:DataContext="{d:DesignInstance vm:MainWindowviewmodel}">

    <Grid>
        <Grid.RowDeFinitions>
            <RowDeFinition Height="Auto"/>
            <RowDeFinition Height="*"/>
            <RowDeFinition Height="*"/>
        </Grid.RowDeFinitions>
        <userControls:NavigationBar Grid.Row="0" DataContext="{Binding Navigator}"/>
        <ContentControl Grid.Row="1" Content="{Binding Navigator.Currentviewmodel}"/>
        <ContentControl Grid.Row="2" Content="{Binding Navigator.Headerviewmodel}"/>
    </Grid>
</Window>


 public class Navigator : ObservableObject,INavigator 
{
    private readonly IviewmodelAbstractFactory _abstractFactory;
    private viewmodelBase _currentviewmodel;
    private viewmodelBase _headerviewmodel;

    public Navigator(IviewmodelAbstractFactory abstractFactory)
    {
        _abstractFactory = abstractFactory;
    }

    public viewmodelBase Currentviewmodel
    {
        get
        {
            return _currentviewmodel;
        }
        set
        {
            _currentviewmodel = value;
            OnPropertyChanged();
        }
    }

    public viewmodelBase Headerviewmodel
    {
        get
        {
            return _headerviewmodel;
        }

        set
        {
            _headerviewmodel = value;
            OnPropertyChanged();
        }
    }

    public ICommand UpdateCurrentviewmodelCommand => new UpdateCurrentviewmodelCommand(this,_abstractFactory);
    public ICommand UpdateHeaderviewmodelCommand => new UpdateHeaderviewmodelCommand(this,_abstractFactory);
}

public class UpdateHeaderviewmodelCommand : ICommand
{
    private INavigator _navigator;
    private readonly IviewmodelAbstractFactory _viewmodelAbstractFactory;

    public UpdateHeaderviewmodelCommand(INavigator navigator,IviewmodelAbstractFactory viewmodelAbstractFactory)
    {
        _navigator = navigator;
        _viewmodelAbstractFactory = viewmodelAbstractFactory;
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        if (parameter is MenuViewType viewType)
        {
            _navigator.Headerviewmodel = _viewmodelAbstractFactory.Createviewmodel(viewType);
        }
    }

    public event EventHandler CanExecuteChanged;
}

public class HeaderviewmodelFactory : IWpfRaddispenserviewmodelFactory<Headerviewmodel>
{
    private readonly ProductionService _service;

    public HeaderviewmodelFactory(ProductionService service)
    {
        _service = service;
    }

    public Headerviewmodel Createviewmodel()
    {
        return new Headerviewmodel(_service);
    }
}

public class Headerviewmodel : viewmodelBase
{
    private readonly ProductionService _service;
    
    public Headerviewmodel(ProductionService service)
    {
        _service = service;
        CreateData();
    }

    private void CreateData()
    {
        _service.CreateTestCycle();
    }
}


public class CycleService : GenericDataService<Cycle>
{
    private readonly IUnitOfWork<WpfRaddispenserDbContext> _uowContext;
    
    public CycleService(IUnitOfWork<WpfRaddispenserDbContext> uowContext)
        : base(uowContext)
    {
        _uowContext = uowContext;
    }

    public void CreateTestCycle()
    {
        var cycleDataService = new GenericDataService<Cycle>(_uowContext);
        var vialDataService = new GenericDataService<Vial>(_uowContext);

        Cycle c = new Cycle();
        c.BatchName = "test";

        Vial v = new Vial();
        v.Name = "Test Vial";
        c.Vials.Add(v);

        _uowContext.CreateTransaction(IsolationLevel.ReadCommitted);
        try
        {
            vialDataService.Create(v);
            _uowContext.Persist();

            var list = vialDataService.GetAll();

            cycleDataService.Create(c);
            _uowContext.Persist();
            _uowContext.Commit();
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            _uowContext.RollBack();
            throw;
        }
        finally
        {
            _uowContext.dispose();
        }
    }
}

我已经以这种方式实现了该服务,因为到目前为止,我不知道该服务的需求,因此我希望有可能在业务逻辑上控制交易,并且有可能混合任何实体以用于任何数据服务。

但是通过在容器上使用这种注册方式

private static Container Bootstrap()
{
    // Create the container as usual.
    var container = new Container();



    // Register your types:
    // Register your windows and view models:

    container.Register<WpfRaddispenserDbContextFactory>(Lifestyle.Transient);
    container.Register<IUnitOfWork<WpfRaddispenserDbContext>,WpfRaddispenserUOW>();
    container.Register(typeof(CycleService));

    container.Register<IWpfRaddispenserviewmodelFactory<Productionviewmodel>,ProductionviewmodelFactory>(Lifestyle.Transient);
    container.Register<IWpfRaddispenserviewmodelFactory<Anagraphicviewmodel>,AnagraphicsviewmodelFactory>(Lifestyle.Transient);

    container.Register<IWpfRaddispenserviewmodelFactory<Headerviewmodel>,HeaderviewmodelFactory>(Lifestyle.Transient);

    container.Register<IviewmodelAbstractFactory,viewmodelAbstractFactory>(Lifestyle.Transient);

    container.Register<INavigator,Navigator>(Lifestyle.Transient);
    container.Register<MainWindowviewmodel>();
    container.Register<MainWindow>();

    //container.Options.EnableAutoVerification = false;
    //container.Verify();
    return container;
}

我不明白为什么第二次收到CycleService时会收到这种异常:

System.ObjectdisposedException:'无法访问已处置的对象。导致此错误的常见原因是,处理从依赖项注入中解析出来的上下文,然后稍后尝试在应用程序中的其他位置使用相同的上下文实例。如果在上下文上调用dispose()或将上下文包装在using语句中,则可能会发生这种情况。如果使用的是依赖项注入,则应让依赖项注入容器负责处理上下文实例。对象名称:“ WpfRaddispenserDbContext”。

我了解到,在所有实例都注册为临时实例之后,每次新建一个实例时,所需的所有实例都是新的还是还有更多?

编辑:我已经通过添加所有调用cycleService的部分进行了修改

基本上我想要的是当用户执行导航命令时(名称UpdateHeaderviewmodel暂时不重要...这只是一个示例) 每次使用新实例创建新的viewmodel以及其自身的视图以及所有必需的服务。

Ps。通过引入这个工厂进行了一些修改,我已经解决了问题

public interface IUnitOfWorkFactory<TContext> where TContext : DbContext
{
    IUnitOfWork<TContext> CreateUnitOfWork();
}

public class WpfRaddispenserUOWFactory:IUnitOfWorkFactory<WpfRaddispenserDbContext>
{
    private readonly WpfRaddispenserDbContextFactory _factory;

    public WpfRaddispenserUOWFactory(WpfRaddispenserDbContextFactory _factory)
    {
        this._factory = _factory;
    }

    public IUnitOfWork<WpfRaddispenserDbContext> CreateUnitOfWork()
    {
        return new WpfRaddispenserUOW(_factory);
    }
}

注册

private static Container Bootstrap()
{
    // Create the container as usual.
    var container = new Container();



    // Register your types:
    // Register your windows and view models:

    container.Register<WpfRaddispenserDbContextFactory>(Lifestyle.Transient);
    container.Register<IUnitOfWork<WpfRaddispenserDbContext>,WpfRaddispenserUOW>();
    container.Register<IUnitOfWorkFactory<WpfRaddispenserDbContext>,WpfRaddispenserUOWFactory>();
    container.Register(typeof(ProductionService));

    container.Register<IWpfRaddispenserviewmodelFactory<Productionviewmodel>,Navigator>(Lifestyle.Transient);
    container.Register<MainWindowviewmodel>();
    container.Register<MainWindow>();

    //container.Options.EnableAutoVerification = false;
    //container.Verify();
    return container;
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...