[英]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單例):
並讓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.