kernel.Get to get singleton instance - ninject

I have ConverterTest class where I need to access ValidateTest class. I can't pass ValidateTest using constructor because ConverterTest is abstract class. If I introduce second constructor to bind ValidateTest I will get numerous problems in derived classes and many things will need to change. So I have tried to pass ValidateTest to ConverterTest using property injection(decorated with inject attribute) but that also do not work because ConverterTest is not created by Ninject and inject properties are ignored. So I decided to create Instance property directly in ValidateTest class and bind instance of itself. To get instance of ValidateTest in ConverterTest class I use kernel.Get<ValidateTest>().Instance. Everything works fine but is it good idea to use kernel.Get to access instance class? Is there any other solution?
public class ValidateTest
{
private readonly ISettingsRepository _settingsRepository;
[Inject]
public ValidateTest Instance { get; set; }
public ValidateTest(ISettingsRepository settingsRepository)
{
_settingsRepository = settingsRepository;
}
}
Binding
kernel.Bind<ISettingsRepository>().To<SettingsRepository>();
kernel.Bind<ValidateAbuse>().ToSelf().InSingletonScope();
Getting instance of ValidateTest using kernel.Get in abstract class where constructor binding is not possible and property binding is not working.
public abstract class ConverterTest
{
public void Execute()
{
NinjectHelper.kernel.Get<ValidateTest>().Instance
}
}

Why not have your subclasses of ConverterTest set the ValidateTest either via an exposed property in ConverterTest or constructor's of their own?
public abstract class ConverterTest
{
protected ValidateTest ValidateTest{get;set;}
public void Execute()
{
ValidateTest.ValidateStuff();
}
}
public class ConcreteConverter : ConverterTest
{
[Inject]
public ConcreteConverter(ValidateTest validateTest)
{
base.ValidateTest = validateTest;
}
}
Or, I think that you could make the property public public ValidateTest ValidateTest{get;set;} and it should work for property injection if you add the appropriate attribute.
public abstract class ConverterTest
{
[Inject]
public ValidateTest ValidateTest{get;set;}
public void Execute()
{
ValidateTest.ValidateStuff();
}
}

Related

Inject DbContextOptions vs DbContext in a repository EF Core

I have the StudentDbContext
public class StudentDbContext : DbContext
{
public StudentDbContext()
{
}
public StudentDbContext(DbContextOptions<StudentDbContext> options)
: base(options)
{
}
public virtual DbSet<Students> Students{ get; set; }
}
and then I have a repository and I try to understand what is the difference if I inject the StudentDbContext vs inject DbContextOptions
Inject the DbContextOptions
class StudentRepository : IStudentRepository
{
private readonly DbContextOptions<StudentDbContext> _context;
public StudentRepository(DbContextOptions<StudentDbContext> context)
{
_context = context;
}
}
Inject StudentDbContext
class StudentRepository : IStudentRepository
{
private readonly StudentDbContext _context;
public StudentRepository(StudentDbContext context)
{
_context = context;
}
}
Are there any advantages or disadvantages in each case?
DbContextOptions class is used to create the options to be used by a DbContext. It configures the database (and other options) to be used for the database context. DbContext class contains DbSet properties for each entity in the model.
If you try to use DbContextOptions in a repository you will have no access to any model since it doesn't have them.
DbContextOptions and DbContextOptions<TContext> have different use cases.
You need to inject DbContextOptions (generic or not) in subtypes of DbContext.
The DbContextOptions instance will contain the options that you have configured in the Startup class:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContextFactory<ConcreateDbContext>(
options => options.UseSqlServer(#"Server=(localdb)\mssqllocaldb;Database=Test")
);
}
If your DbContext implementation is not supposed to be inherited from, you will inject in your ConcreateDbContext the generic version of options type DbContextOptions<ConcreateDbContext>, and this ensures that the correct options for the specific DbContext subtype are resolved from dependency injection. You can also, mark your ConcreateDbContext as sealed, as the class is not designed to be inherited from.
public sealed class ConcreateDbContext: DbContext
{
public ConcreateDbContext(DbContextOptions<ConcreateDbContext> contextOptions)
: base(contextOptions)
{
}
}
In case that you want to have a DbContext that is intended to be inherited from, you are supposed to expose a protected constructor which will take as a parameter the non-generic version of DbContextOptions.
public class BaseDbContext: DbContext
{
protected BaseDbContext(DbContextOptions contextOptions)
: base(contextOptions)
{
}
}
In case you want to have a DbContext that is intended to be both instantiated and inherited from, you will have two constructors, one taking the generic, and one the non-generic version of DbContextOptions.
And when you want to interact with the data in your database, you will inject the concrete DbContext implementation (in your case StudentDbContext).

How can I get HttpContext inside an abstract class in ASPNETCore

I have the following Repository:
public class TestRepository : WebCaller<Data>, ITestRepository
{
string connString = this.GetConnectionString();
.... some code here
}
In my Repository I can do Dependency Injection to the constructor without a problem.
In my abstract class WebCaller I need to get access to HttpContext somehow, I was reading that you can Inject IHttpContextAccessor to get access to the context, but because this is an Abstract class, that also lives outside the Web project, I can't have a constructor.
I was trying to do this:
public abstract class WebCaller<T> : WebRequest, IDisposable
{
//[Inject]
public ITestRepository TestRepo
{
get
{
return this.HttpContext.RequestServices.GetRequiredService<ITestRepository >();
}
}
..... more code here
}
Was trying to use Inject attribute but was reading that is no longer available, so should be other way to pass HttContext to the abstract class.
You can have a constructor on your abstract class. Just inject IHttpContextAccessor to it. Then any derived class will also take IHttpContextAccessor and pass it to its base constructor (your abstract class constructor). You can make the abstract class constructor protected.
Like:
public abstract class WebCaller<T> : WebRequest, IDisposable
{
protected WebCaller(IHttpContextAccessor contextAccessor)
{
}
}
public class TestRepository : WebCaller<Data>, ITestRepository
{
public TestRepository(IHttpContextAccessor contextAccessor) : base(contextAccessor)
{
}
string connString = this.GetConnectionString();
.... some code here
}

check that property setter was called

I have a class I am unit testing and all I want to do is to verify that the public setter gets called on the property. Any ideas on how to do this?
I don't want to check that a value was set to prove that it was called. I only want to ensure that the constructor is using the public setter . Note that this property data type is a primitive string
This is not the sort of scenario that mocking is designed for because you are trying to test an implementation detail. Now if this property was on a different class that the original class accessed via an interface, you would mock that interface and set an expectation with the IgnoreArguments syntax:
public interface IMyInterface
{
string MyString { get; set; }
}
public class MyClass
{
public MyClass(IMyInterface argument)
{
argument.MyString = "foo";
}
}
[TestClass]
public class Tests
{
[TestMethod]
public void Test()
{
var mock = MockRepository.GenerateMock<IMyInterface>();
mock.Expect(m => m.MyString = "anything").IgnoreArguments();
new MyClass(mock);
mock.VerifyAllExpectations();
}
}
There are 2 problems with what you are trying to do. The first is that you are trying to mock a concrete class, so you can only set expectations if the properties are virtual.
The second problem is the fact that the event that you want to test occurs in the constructor, and therefore occurs when you create the mock, and so occurs before you can set any expectations.
If the class is not sealed, and the property is virtual, you can test this without mocks by creating your own derived class to test with such as this:
public class RealClass
{
public virtual string RealString { get; set; }
public RealClass()
{
RealString = "blah";
}
}
[TestClass]
public class Tests
{
private class MockClass : RealClass
{
public bool WasStringSet;
public override string RealString
{
set { WasStringSet = true; }
}
}
[TestMethod]
public void Test()
{
MockClass mockClass = new MockClass();
Assert.IsTrue(mockClass.WasStringSet);
}
}

VB.Net and access via a variable of an interface type

How do I make the properties of a class available in an inheriting class, for a variable that is declared to be the type of one of the interfaces implemented by that class?
What I have done so far is to create an abstract class MyAbstract with the keyword MustInherit and in the inheriting class MyInheritingClass I have added inherits and then the name of the abstract class. Now this is all fine, but in my inheriting class, if I create an interface on that class MyInterface and use that interface elsewhere in my code, I have then found that I cannot see the properties from my abstract class, on the variable declared with that interface.
Am I doing something wrong here, or is there something else that I need to do?
An example would be as follows:
Public MustInherit Class MyAbstract
Private _myString as String
Public Property CommonString as String
Get
Return _myString
End Get
Set (value as String)
_myString = value
End Set
End Property
End Class
Public Class MyInheritingClass
Inherits MyAbstract
Implements MyInterface
Sub MySub(myParameter As MyInterface)
myParameter.CommonString = "abc" ' compiler error - CommonString is not a member of MyInterface.
End Sub
'Other properties and methods go here!'
End Class
So, this is what I am doing, but when I use MyInterface, I cannot see the properties of my Abstract Class!
Unless I've completely misunderstood your question, I'm not sure why you are confused by this behavior. Not only is that how it should work, but that is also how it works in c#. For instance:
class Program
{
private abstract class MyAbstract
{
private string _myString;
public string CommonString
{
get { return _myString; }
set { _myString = value; }
}
}
private interface MyInterface
{
string UncommonString { get; set; }
}
private class MyInheritedClass : MyAbstract, MyInterface
{
private string _uncommonString;
public string UncommonString
{
get { return _uncommonString; }
set { _uncommonString = value; }
}
}
static void Main(string[] args)
{
MyInterface test = new MyInheritedClass();
string compile = test.UncommonString;
string doesntCompile = test.CommonString; // This line fails to compile
}
}
When you access an object through any interface or base class, you will only ever have access to the members that are exposed by that interface or base class. If you need to access a member of MyAbstract, you need to cast the object as either MyAbstract or MyInheritedClass. This is true in both languages.

Injecting my UnitOfWork into my Repository Constructor

Im very new but on a quest to learn nhibernate and DI with structuremap so am making an app to test everything out.
I am having some problems injecting my unitofwork into my base repository. I create a unitofwork on every request then either commit or rollback at the end. But when tryin to inject into my base repository its always null when i go to use it in my methods. More specifically i get this error: "Object reference not set to an instance of an object". Any ideas what im doing wrong and if this is the correct route i should be going?
Many thanks in advance.
Base Repository:
public abstract class Repository<T> : IRepository<T>
{
public readonly IUnitOfWork _unitOfWork;
public Repository(IUnitOfWork UnitOfWork)
{
UnitOfWork = _unitOfWork;
}
public Repository() {}
public void Save(T obj)
{
_unitOfWork.CurrentSession.Save(obj);
}
}
StructureMap registry thats set in my application_start:
public class NHibernateRegistry : Registry
{
public NHibernateRegistry()
{
For<IUnitOfWork>().HybridHttpOrThreadLocalScoped().Use<UnitOfWork>();
For<ISession>().HybridHttpOrThreadLocalScoped().Use(context => context.GetInstance<ISessionFactory>().OpenSession());
For<ISessionFactory>().Singleton().Use(NHibernateSessionFactory.GetSessionFactory());
}
}
Update:
The baserepository is inherited by specific repositorys ie ArticleRepository then im injecting that into my aspx pages on application_start. Then my aspx page inherits a basepage where the buildUp takes place. And i access the repository like this:
public IArticleRepository ArticleRepo { get; set; }
public void SaveThing()
{
ArticleRepo.Save(object);
}
This gets called on application_start:
public class Bootstrapper
{
public static void BootStrap()
{
ObjectFactory.Configure(x =>
{
x.AddRegistry<NHibernateRegistry>();
x.AddRegistry<WebRegistry>();
});
}
}
And in the webregistry:
For<IArticleRepository>().Use<ArticleRepository>();
There is a good chance your ArticleRepository doesn't have a constructor that takes an IUnitOfWork as a parameter make sure you have the following
public class ArticleRepository : Repository<Article>
{
public ArticleRepository(IUnitOfWork unitOfWork) : base(unitOfWork)
{
}
...
}
Remember Strcuture map uses the greediest constructor on the class that it instantiates. Since your abstract repository class will never be instantiated it will not use its constructors. I would also suggest not having any default constructors if your classes need to have their dependencies injected that way. Less chance for errors that way.
public readonly IUnitOfWork _unitOfWork;
public Repository(IUnitOfWork UnitOfWork)
{
UnitOfWork = _unitOfWork;
}
I think you mean to write
public readonly IUnitOfWork _unitOfWork;
public Repository(IUnitOfWork UnitOfWork)
{
_unitOfWork = UnitOfWork;
}
You were assigning the local variable to the parameter instead of the parameter to the local variable.
Edit: Also you should write your parameter with a lowercase U 'unitOfWork' instead of 'UnitOfWork'