尝试从ASP.NET MVC Controller Action访问单例类时,我得到空引用异常。我使用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”);
答案 0 :(得分:3)
您的_service变量始终为null。因此,您可能会获得null引用。
private static IService<Administrator> _service;
此变量从不实例化(手动或通过Autofac)
当你调用你的方法时,这是可能导致空引用的代码。
var getImage = _service.GetByIdAsync(userId);
因为_service
为空
对于所有正在完成的Autofac连线,我们没有向Autofac指示此类需要自动实例化的地方。该类似乎不是控制器(MVC或API)或对控制器的任何依赖。
此外,静态_service
变量对Autofac没有帮助。
要解决这个问题,您可能想要根据控制器或更好的方式重新考虑这个类,一个依赖(构造函数参数)到一个控制器,使用_service和变量这样的变量而不是静态变量,其中Autofac不能帮助你。
这样,当控制器由Autofac实例化时,它会自动创建一个&#39; UserControlHelper
&#39;的实例。对你而言。
回答你的评论(你需要一个UserControlHelper单身):
让Autofac知道将其实例化为单身人士。
public class MyController: Controller
{
public MyController(UserControlHelper helper)
{
ViewBag.FullName = helper.GetUserData(UserId, "Name");
}
}
当您使用Autofac注册此课程时,您可以执行以下操作:
build.RegisterType<UserControlHelper>().SingleInstance();
这意味着你必须删除Instance变量和类中任何类似singleton的逻辑。并且还将静态方法转换为实例方法。并将构造函数转换为公共构造函数。
最好让Autofac / frameworks完成Singletons /其他此类功能的繁重工作。 (懒惰变量是另一种这样的工具)
我们可以专注于保持您的课程与业务逻辑相关。
如果你真的想自己做单例实现,你仍然可以用autofac注册它:
builder.RegisterInstance<UserControlHelper>(singletonInstanceYouConstructed);
但总的来说,我发现让Autofac管理整个生命周期管理会更简单。