簡體   English   中英

使用Autofac訪問單例時出現Null Reference異常

[英]Null Reference exception when accessing a singleton with Autofac

嘗試從ASP.NET MVC控制器操作訪問單例類時,出現了空引用異常。 我使用Autofac作為IoC容器。

這是代碼:

注冊依賴方法:

public static void RegisterDependencies()
    {
        var builder = new ContainerBuilder();
        const string nameOrConnectionString = "name=DefaultConnection";
        builder.RegisterApiControllers(typeof(WebApiConfig).Assembly);
        builder.RegisterControllers(typeof(MvcApplication).Assembly);
        builder.RegisterModule<AutofacWebTypesModule>();

        builder.RegisterGeneric(typeof(EntityRepository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope();
        builder.RegisterGeneric(typeof(Service<>)).As(typeof(IService<>)).InstancePerLifetimeScope();
        builder.RegisterType(typeof(UnitOfWork)).As(typeof(IUnitOfWork)).InstancePerLifetimeScope();
        builder.Register<IEntitiesContext>(b =>
        {
            var logger = b.Resolve<ILogger>();
            var context = new InterfaceContext(nameOrConnectionString, logger);
            return context;
        }).InstancePerRequest();
        builder.Register(b => NLogLogger.Instance).SingleInstance();
        builder.Register(b => UserControlHelper.Instance).SingleInstance();
        builder.RegisterModule(new IdentityModule());

        var container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
        GlobalConfiguration.Configuration.DependencyResolver =
             new AutofacWebApiDependencyResolver(container);
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    }

UserControlHelper類:

public class UserControlHelper
{
    private static volatile UserControlHelper _instance;
    private static readonly object SyncRoot = new object();

    private static IService<Administrator> _service;
    private static IService<Customer> _customerService;


    private UserControlHelper() { }

    private UserControlHelper(IService<Administrator> service, IService<Customer> customerService)
    {
        _service = service;
        _customerService = customerService;
    }

    public static UserControlHelper Instance
    {
        get
        {
            if (_instance == null)
            {
                lock (SyncRoot)
                {
                    if (_instance == null)
                        _instance = new UserControlHelper(_service, _customerService);
                }
            }

            return _instance;
        }
    }

    public static string GetUserData(int userId, string type)
    {
        var getImage = _service.GetByIdAsync(userId);

        switch (type)
        {
            case "Image":
                {
                    return getImage.GetAwaiter().GetResult().Image;
                }
            case "Name":
                {
                    return getImage.GetAwaiter().GetResult().FullName;
                }
            case "Email":
                {
                    return getImage.GetAwaiter().GetResult().Email;
                }

            case "AllUsers":
                {
                    return _customerService.GetCountAsync(userId).GetAwaiter().GetResult().ToString();
                }

            default:
                return "No Data";
        }
    }
}

我這樣稱呼它:

ViewBag.FullName = UserControlHelper.GetUserData(UserId,“ Name”);

您的_service變量將一直為null。 因此,您可能會得到空引用。

private static IService<Administrator> _service;

永遠不會實例化此變量(手動或通過Autofac)

當您調用方法時,這是可能導致空引用的代碼。

    var getImage = _service.GetByIdAsync(userId);

因為_service為null

對於所有完成的Autofac聯結,沒有任何地方可以向Autofac指示需要自動實例化此類。 該類似乎不是控制器(MVC或API)或對該控制器的任何依賴項。

同樣, _service變量為靜態變量對Autofac無效。

要解決該問題,您可能需要重新考慮此類,例如控制器或更高版本,控制器的依賴項(構造函數參數),_service和諸如實例變量而非靜態變量之類的變量,而Autofac不能為您提供很多幫助。

這樣,當控制器由Autofac實例化時,它將為您自動創建“ UserControlHelper ”的實例。

回答您的評論(您需要一個UserControlHelper單例):

  1. 您可以為此使用Autofac。
  2. 我們將使該類成為控制器的構造函數參數。
  3. 並讓Autofac知道將其實例化為單例。

     public class MyController: Controller { public MyController(UserControlHelper helper) { ViewBag.FullName = helper.GetUserData(UserId, "Name"); } } 

在Autofac上注冊此類時,您可以執行以下操作:

build.RegisterType<UserControlHelper>().SingleInstance();

這意味着您必須刪除Instance變量和類中的任何類單例邏輯。 並將靜態方法轉換為實例方法。 並將構造函數轉換為公共的。

最好讓Autofac / frameworks完成Singletons /其他類似功能的繁重工作。 (惰性變量是另一個這樣的工具)

我們可以專注於使您的課程與業務邏輯相關。

而且,如果您確實想自己執行單例實現,則仍可以使用以下方式在autofac中注冊它:

builder.RegisterInstance<UserControlHelper>(singletonInstanceYouConstructed);

但是總的來說,我發現讓Autofac管理整個生命周期管理更為簡單。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM