What is a sense to create set of constructors if there is still possibility to initiate any set of fields for a class using curly braces? Never thought about that before but from my experience i could make few constructors to secure the way class can be constructed. Nevertheless every time curly bracets can be used which to me is something like a hack overcoming constructors. Am I missing something here?
If you are allowing the fields and properties to be set by the caller, yes, there is no difference. But the constructor is not only about setting fields, it holds the logic to instantiate an object.
If you want the object to be immutable and be changed only by itself, you should use readonly fields and read-only properties.
Read-only properties are declared by not providing a setter, or more simply, the set keyword.
An example:
public class YourClass
{
readonly string readonlyField;
public int ImmutableIntProperty {get;}
public YourClass(string field, int value)
{
readonlyField = field;
ImmutableIntProperty = value;
}
}
Constructors are not only for object initialization, but we can also use it to inject dependencies.
For Example: we can inject the dependency of Logger class to Constructor to use it throughout the class.
public class Demo
{
private readonly ILogger<Demo> _logger;
public Demo(ILogger<Demo> logger)
{
// Use _logger throughout the class
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public void Log()
{
// _logger.Log(message);
}
}
NOTE: Some dependencies are resolved by .Net itself, but in case of custom types we need to resolve dependency by our self. This will help to to achieve loose coupling between types and is extensively used in multi tier projects.
Related
Take the following two classes:
public class PersonA
{
private readonly ILogger<PersonA> _logger;
public PersonA() : this(new NullLogger<PersonA>())
{}
public PersonA(ILogger<PersonA> logger)
{
_logger = logger;
}
public void SomeMethod()
{
_logger.LogDebug("SomeMethod invoked");
}
}
public class PersonB
{
private readonly ILogger<PersonB>? _logger;
public PersonB(ILogger<PersonB>? logger = null)
{
_logger = logger;
}
public void SomeMethod()
{
_logger?.LogDebug("SomeMethod invoked");
}
}
The way that ILogger<T> is passed is very similar in both and both approaches work, but is there any reason why you'd favour ILogger<T>? defaulting to null over two ctors one defaulting to NullLogger<T> and ensuring that _logger is never null or vice-versa?
Are any differences in performance?
As pointed out by one comment, there is so little difference in tearms of performance and object allocation that I would actually avoid to compare these two approaches in tearms of performance.
I would instead suggest the following considerations:
having two constructors is worst in terms of design. That will make creating your object harder, because the object creator has to choose between the two and have to understand the different semantic. It is much better having one and only one way to create an object: that's simpler and there is no ambiguity about the way the object should be created
as long as possible I would avoid handling null values. Code using objects that can potentially be null is harder to maintain, because if you accidentally forget the ? operator when you refactor your code you will get a NullReferenceException at runtime. You would need to write and maintain additional unit tests for the null case, in order to be sure you didn't forget a ? somewhere in your code.
Based on these two points, a better design is the following:
have a class with only one constructor
do not allow the _logger field to be nullable, that is it's type should be ILogger<Person> instead of ILogger<Person>?. In cases when you don't care about logging, use the null object pattern and inject an instance of NullLogger<Person> in the constructor (instead of using a null reference).
As a final note do not instantiate NullLogger<T>. Use, instead, the NullLogger<T>.Instance static field. By doing so, you will access to a shared cached instance of the class and you will avoid to allocate a new object (it's fine to do so for stateless classes like NullLogger<T>). This is good in tearms of memory usage and garbage collector pressure.
Final design of the class is the following:
public class Person
{
private readonly ILogger<Person> _logger;
public Person(ILogger<Person> logger)
{
// guard against null
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public void SomeMethod()
{
_logger.LogDebug("SomeMethod invoked");
}
}
// if you don't care about logging
var person = new Person(NullLogger<Person>.Instance);
I want to either guarantee that fields used in the constructor are populated before construction, or somehow throw an exception if one of these fields is used in the constructor.
I am writing an injection framework for Unity3D. I have a use-case like this that emerged:
public class TestInjectable : IInjectable
{
[Inject] TestDependency testDependency;
int testValue;
public TestInjectable()
{
testValue = testDependency.value;
//testValue is NULL here, because testDependency is injected AFTER construction
}
}
public class TestDependency : IInjectable
{
public int value = 5;
}
If I go like this, it works jus fine:
public class TestInjectable : IInjectable
{
TestDependency testDependency;
int testValue;
public TestInjectable(TestDependency testDependency)
{
testValue = testDependency.value;
//testValue is 5 here, because testDependency is injected as a constructor parameter
}
}
public class TestDependency : IInjectable
{
public int value = 5;
}
I can use construction-parameter injection to make this work. However, after adding the [Inject] attribute for class fields, the idea of using those fields at construction, without constructor parameters, has entered the mix.
First: It would be nice to make the above work somehow... The created instance is required to set its field values, meaning construction must occur first regardless. I am not sure how to get around needing the constructor to run before injecting the fields.
Second: I would also be fine just throwing an exception for now, alerting the user that using an [Inject] field inside the constructor cannot occur... I was not able to find a solution for detecting if a field is used inside a constructor.
Third: If neither of these can be accomplished, I will have to rely on users reading the documentation, where I can explain this issue. Or, I will have to consider removing the [Inject] feature, which besides for this pit-fall, can be very useful for defining injection.... I would hate to take it out.
I have an abstract factory which creates some service represented by IService interface. In the factory I have two Create methods, because at one of them I allow the consumer to pass an existing IServiceLogger instance to be used by the constructed service tree.
public interface IMyServiceFactory {
IMyService Create(IServiceLogger loggerInstance);
IMyService Create();
}
Because an IServiceLogger should be shared among the service tree, I use the InCallScope when binding it to a concrete implementation.
How can I implement this scenario with Ninject? I've tried the following approaches.
1. Manually create a factory implementation
internal class MyServiceFactory : IMyServiceFactory {
private IResolutionRoot _kernel;
public MyServiceFactory
public IMyService Create(IServiceLogger loggerInstance) {
// what should go here? how can I pass the existing instance to Ninject Get method and make Ninject to use it for the whole resolution tree, just as it were created by Ninject and used as InCallScope?
}
// this one is trivial...
pulbic IMyService Create() {
return _kernel.Get<IMyService>();
}
}
UPDATE
Actually I've found a messy and not too safe way for this. I can get the current bindings via GetBindings, then Rebind IServiceLogger ToConstant, then Get the IMyService instance, and finally restore the original bindings with AddBinding. I don't like it, it feels stinky and what's worse, it's not thread-safe, because another thread can request for a IMyService in the middle of this code and hence use the local temporary binding.
2. Use Ninject.Extensions.Factory
Just use the ToFactory binding, but that's not working, because it just tries to use the parameter as a simple constructor argument (if applicable), and not as an object for the whole resolution tree.
I would give more control to the Kernel of Ninject and do not create a class for the factory at all.
And use Func binding in Ninject like this:
Bind<Func<IMyService>>().ToMethod(s => CreateService);
By binding of the ILoggerService or not binding this you can controll centrally whether you have logger or not in your service.(try by just comment it out)
Here implementation of the Bootstrapper:
public class Bootstrapper
{
private IKernel _kernel = new StandardKernel();
public Bootstrapper()
{
_kernel.Bind<MyStuff>().ToSelf();
_kernel.Bind<IServiceLogger>().To<ServiceLogger>();
_kernel.Bind<IMyService>().To<MyService>();
_kernel.Bind<Func<IMyService>>().ToMethod(s => CreateService);
}
public IKernel Kernel
{
get
{
return _kernel;
}
set
{
_kernel = value;
}
}
private IMyService CreateService()
{
if(_kernel.GetBindings(typeof(IServiceLogger)).Any())
{
return _kernel.Get<IMyService>(new ConstructorArgument("logger", _kernel.Get<IServiceLogger>()));
}
return _kernel.Get<IMyService>();
}
}
Implementation of consumer class for the factory:
internal class MyStuff
{
private readonly Func<IMyService> _myServiceFactory;
public MyStuff(Func<IMyService> myServiceFactory)
{
_myServiceFactory = myServiceFactory;
_myServiceFactory.Invoke();
}
}
Simple implementation of MyService:
internal class MyService
:IMyService
{
public MyService()
{
Console.WriteLine("with no parameters");
}
public MyService(IServiceLogger logger)
{
Console.WriteLine("with logger parameters");
}
}
Simple ServiceLogger:
internal class ServiceLogger
:IServiceLogger
{
public ServiceLogger()
{
}
}
internal interface IServiceLogger
{
}
IMPORTANT UPDATE
While my original answer gave me a working solution, by an accidental InteliSense navigation I've just found that there is a built-in tool for exactly this issue. I just have to use the built-in TypeMatchingArgumentInheritanceInstanceProvider which does this, and even more, because there are no more needs for naming conventions due to the parameter type matching.
It would be good to have a more detailed documentation about these options, or maybe it's just me who can't find it currently.
ORIGINAL ANSWER
I tried a few ways, and ended up with a slightly different, kind of a convention based approach utilizing Ninject's context parameter inheritance.
The convention is used at constructor argument naming through the dependency tree. For example whenever an IServiceLogger instance is injected to a service class, the argument should be called serviceLogger.
With the above convention in mind, I've tested the following approach. Firstly I've implemented a custom instance provider for the factory extension. This custom provider overrides the mechanism for creating constructor parameters for the context to let the developer specify several named arguments which should be set as inherited. This way all the parameters with the specified names will inherit through the whole request graph during the get operation.
public class ParameterInheritingInstanceProvider : StandardInstanceProvider
{
private readonly List<string> _parametersToInherit = new List<string>();
public ParameterInheritingInstanceProvider(params string[] parametersToInherit)
{
_parametersToInherit.AddRange(parametersToInherit);
}
protected override IConstructorArgument[] GetConstructorArguments(MethodInfo methodInfo, object[] arguments)
{
var parameters = methodInfo.GetParameters();
var constructorArgumentArray = new IConstructorArgument[parameters.Length];
for (var i = 0; i < parameters.Length; ++i)
constructorArgumentArray[i] = new ConstructorArgument(parameters[i].Name, arguments[i], _parametersToInherit.Contains(parameters[i].Name));
return constructorArgumentArray;
}
}
Then after at binding configuration I just threw it in with the corresponding parameter name.
kernel.Bind<IMyServiceFactory>().ToFactory(() => new ParameterInheritingInstanceProvider("serviceLogger"));
Finally I reviewed parameter naming, and for exampled changed loggerInstance in the factory interface to serviceLogger to match the convention.
This solution is still not the nicest one as it has several limitations.
It is error prone. One can make bugs which are hard to track by not keeping the naming convention, because currently it silently fails if the convention does not match. This could be improved probably, I'll think about it later.
It handles only constructor injection, however this should not be a big issue as that's the suggested technique. For example I almost never do other kind of injections.
I realise this was asked a long time ago but I was looking to do the same sort of thing myself and finally worked out that you can use the IParameter array passed to the Get() method to specify a ContructorArgument to use only for the current Get() call. This allowed me to use a specific constructor value when creating a Hangfire Job allowing the Hangfire job to use a different database connection on each invocation if required.
EnvironmentName forcedEnv = new EnvironmentName() { Name = dbName };
// For this instantiation, set the 'envName' parameter to be the one we've specified for this job
var instance = ResolutionExtensions.Get((IResolutionRoot) _kernel, jobType,
new IParameter[] {new ConstructorArgument("envName", forcedEnv, true)});
return instance;
By setting the shouldInherit value to true you can ensure the value gets passed down the resolution chain. So it get's passed to any objects in the dependency tree that use that argument (but only for this particular instantiation).
I have a class with internal constructor and want to Resolve it from Unity (2.0).
public class MyClass {
internal MyClass(IService service) {
}
}
then I'm doing
_container.Resolve<MyClass>();
when I do so I have an exception
Exception is: InvalidOperationException - The type MyClass cannot be constructed.
IService is registered and the only problem is that constructor is internal.
I really want this class to be public, but I want it to be creatable only via a factory (in which I'm actually calling container.Resolve<MyClass>()).
Is there a way to make Unity see that internal constructor? Like InternalsVisibleTo or something?
I dug a little into how you might extend Unity for this purpose, and found some interesting information.
First, it seems that Unity selects which constructor to use by internally resolving an IConstructorSelectorPolicy. Included in Unity is the public abstract class ConstructorSelectorPolicyBase<TInjectionConstructorMarkerAttribute>, which includes this gem:
/// <summary>
/// Choose the constructor to call for the given type.
/// </summary>
/// <param name="context">Current build context</param>
/// <param name="resolverPolicyDestination">The <see cref='IPolicyList'/> to add any
/// generated resolver objects into.</param>
/// <returns>The chosen constructor.</returns>
public SelectedConstructor SelectConstructor(IBuilderContext context, IPolicyList resolverPolicyDestination)
{
Type typeToConstruct = context.BuildKey.Type;
ConstructorInfo ctor = FindInjectionConstructor(typeToConstruct) ?? FindLongestConstructor(typeToConstruct);
if (ctor != null)
{
return CreateSelectedConstructor(context, resolverPolicyDestination, ctor);
}
return null;
}
FindInjectionConstructor and company are private static methods in this class which ultimately end up calling Type.GetConstructors (the overload with no parameters, which only returns public constructors). This tells me that if you can arrange for Unity to use your own constructor selector policy, which would be able to select any constructor, you are golden.
There is good documentation about how to make and utilize your own container extensions, so I imagine it's quite possible to make your own CustomConstructorSelectorPolicy that includes the relevant portions of DefaultUnityConstructorSelectorPolicy (which derives from the abstract base class and is the default unless you register something else) and ConstructorSelectorPolicyBase (deriving from this directly would probably not work well because key methods are not virtual, but you can reuse the code).
Therefore I 'd say it's doable with a moderate amount of hassle, but the end result would be quite "pure" from an engineering point of view.
Unity will only look at public constructors, so you need to make this constructor public.
I really want this class to be public,
but I want it to be creatable only via
a factory
In that case, create a factory:
public class MyClassFactory : IMyClassFactory
{
private readonly IService service;
public MyClassFactory(IService service)
{
this.service = service;
}
MyClass IMyClassFactory.CreateNew()
{
return new MyClass(this.service);
}
}
And register:
_container.Register<IMyClassFactory, MyClassFactory>();
And resolve:
_container.Resolve<IMyClassFactory>().CreateNew();
You can also use Unity's InjectionFactory:
container.Register<MyClass>(new InjectionFactory(c =>
{
return new MyClass(c.Resolve<IService>());
}));
For this to work the assembly that holds this code should be able to see the internals of the assembly that holds the MyClass. In other words the MyClass assembly should be marked with InternalsVisibleTo.
What would also work is the following:
public static class MyClassFactory
{
public static MyClass CreateNew(IService service)
{
return new MyClass(service);
}
}
container.Register<MyClass>(new InjectionFactory(c =>
{
return MyClassFactory.Create(c.Resolve<IService>());
}));
Although you won't have to make the constructor public, it is a great way to obfuscate your code :-)
Just make the class internal and the constructor public...
Interface public
Class internal
Constructor of class public.
It's possible there are workarounds/hacks that would allow you to do this with Unity 9I don't know if any), but in general if you want a class to be managed by Unity (or any IOC container), it needs to be public with a public constructor.
One option might be to make an abstract factory that creates the class that has a public constructor, and keep the class's constructor internal. The downside is then your factory will be managed by Unity, but your class itself will not.
public sealed class Singleton
{
static readonly Singleton instance=new Singleton();
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Singleton()
{
}
Singleton()
{
}
public static Singleton Instance
{
get
{
return instance;
}
}
}
I think even on removing readonly keyword from the instance member instantiation, the singleton would still work equally well.
Its static, only one instance would exist.
The value cant change, as it has no setter.
Its a sealed class, cant be subclassed.
Please help me correct my understanding of the concepts here.
Because if the field were not marked readonly it could be modified within the Singleton class. Of course, it still could not be modified by the outside world, but a singleton really isn't a singleton if there is more than one instance of it during the lifetime of your program, and the readonly specifier enforces the semantics that you want in a singleton class.
EDIT in response to:
Its static, only one instance would exist.
The value cant change, as it has no setter.
Static variables can certainly be set to reference different objects at runtime. The value can change, if only within the class due to it being private. If the class were implemented such that the field was only ever assigned to once, it wouldn't be a problem in practice. However, since the assumed intention is that the singleton instance will never change, the readonly modifier guarantees those semantics outside of the constructor. It's not essential because clients of the class cannot change the reference, but it is preferred because it a) makes the intent of the code clear, and b) prevents the reference from being changed even within the class.
Using readonly is not essential in this case but it is something that enforces the semantics of the code by indicating the nature of the field. Personally I always use the readonly keyword for all field declarations whose value is going to be initialized only once. It also might help the compiler perform some optimizations under certain circumstances.
I don't think readonly must present here - it makes sense only for lazy initialization. If you static field marked as readonly - it could be initialized only during declaration or in static constructor. If instance is not marked as readonly - you can initalize it during first call to Instance property.
BTW I think it's better to use singleton with double-check locking:
public sealed class Singleton
{
private Singleton()
{
// Initialize here
}
private static volatile Singleton _singletonInstance;
private static readonly Object syncRoot = new Object();
public static Singleton Instance
{
get
{
if(_singletonInstance == null)
{
lock(syncRoot))
{
if(_singletonInstance == null)
{
_singletonInstance = new Singleton();
}
}
}
return _singletonInstance;
}
}
}
I removed the readonly in a class because I wanted to make a OneAtaTimeleton (instead of a Singleton).
Why? Well, the class contained some configuration that I wanted the user (administrator) to be able to change while the app was running. So, I added a static Reload() method to the class, which has:
instance = new Configuration();
hence the need to remove the readonly.
The private version of the constructor loads the config (via a non-static method).