Assign class fields with reflection BEFORE construction of the instance - c#

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.

Related

C# - When i try to create constructor, i get CS7036 error

Firstly, sorry for my English. I hope i can explain my problem.
I have class like this
public class CarCommandExecutorBase
{
protected readonly ICarCommand CarCommand;
public CarCommandExecutorBase(ICarCommand carCommand)
{
CarCommand = carCommand;
}
}
Also i have class like this
public class CarStringCommandExecutor : CarCommandExecutorBase, IStringCommand
{
public CarStringCommandExecutor(Car car)
{
// this Constructor gives me an error.
}
public void ExecuteCommand(string commandObject)
{
}
}
Error message:
[![error][1]][1]
What's the reason and how can i fix it? Thanks.
Since the only constructor in CarCommandExecutorBase is defined like this
public CarCommandExecutorBase(ICarCommand carCommand)
{
CarCommand = carCommand;
}
you have to pass an ICarCommand when creating an instance of CarCommandExecutorBase.
You have to provide an ICarCommand through the constructor of CarStringCommandExecutor, because when instantiating a derived type the base constructor(s) also get called.
See this answer for more detailed information about this: https://stackoverflow.com/a/1882778/8450550
You could do something like this to solve this error:
public class CarStringCommandExecutor : CarCommandExecutorBase, IStringCommand
{
...
public CarStringCommandExecutor(Car car, ICarCommand carCommand)
: base(carCommand) // base() points to the constructor of the base class
{
...
}
or maybe this
public class CarStringCommandExecutor : CarCommandExecutorBase, IStringCommand
{
...
public CarStringCommandExecutor(Car car)
: base(null) // passing null but be aware of NullReferenceExceptions
{
...
}
or you add another constructor to CarCommandExecutorBase which expects no arguments:
public class CarCommandExecutorBase
{
protected readonly ICarCommand CarCommand;
public CarCommandExecutorBase(ICarCommand carCommand)
{
CarCommand = carCommand;
}
// mark this constructor as protected, so only deriving types can call it
protected CarCommandExecutorBase()
{
}
}
Which solution works best in your case is up to you.
One of the things that isn't immediately apparent, thanks to "compiler magic", about a C# class is that every class has a constructor
It needs to be this way because it's a rule that object construction happens in a tree; you construct some class Z which inherits from Y which inherits from X which inherits from object, and Z's cosntructor invokes Y's invokes X's invokes object's, then they finish, in order of object, X, Y, Z and you have your nicely constructed thing - every constructor on the way up the tree had its chance to do its init and ready the object for use (the part of it that each constructor was responsible for)
Even classes that don't seem to have constructors, have constructors:
class X {
}
If you don't provide a constructor, C# provides one for you. You never see it in your source code; just imagine that in between reading the file and compiling it, the compiler inserts it for you. It takes no parameters, has no code, and does nothing other than call its base:
class X {
X():base() { } //C# invisibly writes this for you
}
If you provide a constructor but don't write the base... bit, C# puts base() in for you behind the scenes (and it always calls the no-argument base()) but critically it doesn't provide an empty constructor if you provided one already
This means if you have a class like:
class X{
X(string message){
...
}
}
Your class X has a constructor, so C# won't provide the empty one, so now anything that tries to construct your class must provide a string message:
X x = new X("hello");
If you now inherit from X, you might do one of 3 things (with Y):
class Y:X{
}
You don't add a constructor, C# adds one, but it just dumbly calls base(), which doesn't work because there is no constructor in X that takes no args:
class Y:X{
Y():base() { }
}
You add a constructor but leave off the base bit. C# adds it, again just literally as base() - this also doesn't work for the same reason
class Y:X{
Y(int myArg) //c# adds base() in here for you
{
...
}
}
You add a constructor that includes a call to base and because you know your base class only has a constructor with a string arg, you pass one:
class Y:X{
Y(int myArg) : base("hello")
{
...
}
}
So you're in scenario 2, and you either need to:
Add a no-arg constructor to the base class so that c#'s auto-inserted stuff works or,
Add a call to base(...) with a suitable argument, to stop C# from putting a base() in
I've left out access modifiers from code in this answer for clarity of demonstrating the essential point. Whether a constructor is accessible or not can also have a bearing on all this, but I deemed it out of scope

Why constructors if curl braces

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.

c# how to initialize or set a default constructor value to a injected dependency from class

I have a class that uses dependency injection:
public class MainClass: IDisposable
{
IUtilityRepository _utilityRepo = null;
public MainClass()
{
}
public MainClass(IUtilityRepository utilityRepo)
{
_utilityRepo = utilityRepo;
}
}
Then my UtilityRepository class has:
public class UtilityRepository : IUtilityRepository
{
private int _userId;
private int _sessionId;
// maybe have here some constructor where i can get some values from MainClass
public UtilityRepository ()
{
// here set the private properties from the MainClass when the dependency is intialized from MainClass
}
public List<string> MethodTestOne(string tempFolder)
{
// here I want to
}
public List<string> MethodTestTwo(string tempFolder)
{
}
}
What I want to do is to pass from MainClass two properties to UtilityRepository class so any method within UtilityRepository can use those values globaly in the class without the need of passing the values to every method in a independant way.
Any clue?
TL;DR: We should inject dependencies into the classes that need them. Classes shouldn't be responsible for providing dependencies to their dependencies.
If MainClass receives userId and sessionId from somewhere, how does it receive them? Presumably they are injected into MainClass, or something that provides them is injected.
If MainClass receives them via injection, UtilityRepository can receive them the same way. If MainClass doesn't receive them via injection, configure your container to inject them into UtilityRepository anyway. That could look like this:
public interface IContext // not the greatest name
{
string UserId { get; }
string SessionId { get; }
}
or
public interface IContextAccessor
{
// where Context is an object containing the values you need.
Context GetContext();
}
Then you configure the container provide a runtime implementation of IContextAccessor that retrieves the values from the current request. Inject IContextAccessor into UtilityRepository.
public class UtilityRepository : IUtilityRepository
{
private readonly IContextAccessor _contextAccessor;
public UtilityRepository(IContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
}
}
If MainClass doesn't need those values (it was only receiving them so it could pass them to something else) then it shouldn't receive them. If MainClass does need them, the fact that UtilityRepository also needs them is coincidental. (You can inject IContextAccessor into MainClass too.) There's no reason why MainClass needs to be responsible for passing them to UtilityRepository.
MainClass depends on an abstraction - IUtilityRepository. It does not and should not know what the concrete implementation of that interface depends on. It shouldn't know anything at all that isn't in that interface. As soon as it does, it no longer "depends" on the interface. It's coupled to the implementation.
That's one of the primary benefits of using an IoC container. Classes get their dependencies from the container, not from each other. Depending on abstractions means that classes don't know how those abstractions are implemented. That in turn means that classes don't know about the the dependencies of their dependencies.
To illustrate: A lamp depends on an abstraction - a power outlet that gets its power from somewhere. It could a be a power grid, a solar panel, a generator, a bicycle, or anything else.
Whatever the implementation of the power source is, it probably has dependencies of its own. A generator needs gasoline. A power grid needs a power plant.
Those dependencies probably have dependencies of their own. A power plant needs someone to shovel coal.
The lamp shouldn't know anything about those dependencies. If using a lamp means:
Plug in the lamp
Turn on the lamp
Put gas in the generator
Then we're no longer depending on an abstraction. We're depending on a generator. It doesn't matter if we declare it as an interface and call it IPowerSupply. The only implementation it can work with is a generator.
The same goes for the power grid. It depends on a power source. That power source might require coal, generators, etc. But what happens if we make the power grid responsible for starting the generator, and then later we want to replace the generator with a massive solar panel array? How will the power grid start the generator when there is no generator?
That's why every class should know as little as possible about its dependencies. If it knows something, it's coupled to that detail. The whole point of Dependency Inversion (depending on abstractions) is to prevent or minimize coupling so that changing one implementation detail doesn't have a ripple effect that forces us to change other things that shouldn't have to change.
IoC containers make it super easy for us to accomplish that. Every class says what it needs by requiring it in the constructor, and the container injects it. If the thing injected has its own dependencies, the container takes care of that too. All of our classes get constructed independently without knowing anything about each other.
Basically, passing parameters to constructor of an implementation introduces coupling which is the opposite of the dependency injection principle.
However, if you define a requirement that every implementation must receive the two parameters userId and sessionId in constructor, the decoupling is preserved, since all implementations adhere to this convention.
To enable such a scenario, MainClass must receive IKernel parameter, rather than IUtilityRepository:
public class MainClass
{
private readonly IUtilityRepository _utilityRepo = null;
public MainClass()
{
}
public MainClass(IKernel kernel)
{
var userId = new Ninject.Parameters.ConstructorArgument("userId", 123);
var sessionId = new Ninject.Parameters.ConstructorArgument("sessionId", 456);
_utilityRepo = kernel.Get<IUtilityRepository>(userId, sessionId);
}
}
In this way UtilityRepository will be able to receive the two parameters in the constructor:
public class UtilityRepository : IUtilityRepository
{
private readonly int _userId;
private readonly int _sessionId;
// maybe have here some constructor where i can get some values from MainClass
public UtilityRepository (int userId, int sessionId)
{
_userId = userId;
_sessionId = sessionId;
}
public List<string> MethodTestOne(string tempFolder)
{
// do something...
}
public List<string> MethodTestTwo(string tempFolder)
{
// do something...
}
}
Note that in such a case, the registration of UtilityRepository must be transient, so that a new instance is created every time it's requested with the specific parameter values:
kernel.Bind<IUtilityRepository>().To<UtilityRepository>().InTransientScope();
One downside of this solution is that MainClass doesn't use constructor parameters any longer in order to explicitly declare its dependencies. The code is now less self-documenting.

C# Creating an object within a class

I'm making a map loading system that uses chunks so that the entire map data doesn't have to be loaded at once.
I have a "World" class, and within that class I'm creating an instance of a class called "ChunkManager".
I'm unsure if creating an instance inside another class is a good idea/considered a "normal" thing to do etc. I've not been able to find anything about this while searching the internet.
So my question is: Should I be creating an instance of a class within a class in the way I have, or will there be problems with doing it this way?
Here is my code, if it's relevant:
class World
{
public string WorldName { get; set; }
ChunkManager chunkManager = new ChunkManager();
public World(string worldName)
{
WorldName = worldName;
}
public void AddChunk(int X, int Y)
{
//Plus other validation code here that I didn't paste
chunkManager.AddChunk(X, Y);
}
}
And ChunkManager:
class ChunkManager
{
public int TotalGeneratedChunks { get; private set; }
private List<Chunk> ChunkList = new List<Chunk>();
public bool CheckIDExists(int IDToCheck)
{
foreach (Chunk i in ChunkList)
{
if (i.UniqueID == IDToCheck)
{
return true;
}
}
return false;
}
public void AddChunk(int X, int Y)
{
ChunkList.Add(new Chunk(TotalGeneratedChunks++, X, Y));
}
}
Your code is fine BUT if either class grows to be more complex and you want to be able to test them independently you should instead define an interface IChunkmanager and inject an instance of ChunkManager into World:
class World
{
public string WorldName { get; set; }
private readonly IChunkManager chunkManager;
public World(string worldName, IChunkManager chunkmanager)
{
this.chunkManager = chunkManager;
...
With this approach you can use a mocking framework to inject a mock IChunkManager and can test the World class independently.
In general classes should be loosely coupled. As soon as you new-up an instance of another class within a class you have tightly-bound them in a way that makes it hard to test them independently (or to reuse them in different situations).
It's perfectly fine to create an instance of a class inside another. chunkManager is what is known as a field and the syntax for initializing it inline along with its declaration is called an initializer. You can find more information on initializers and how they are different from initializing via the constructor in this blog series by Eric Lippert
Part 1
Part 2
It might some times be a better idea to initialize fields via the constructor though as this lets you use dependency injection (parameter injection to be precise) which can greatly improve the testability and modularity of your code. If you're interested in learning more about dependency injection I suggest purchasing and reading this book.
Standard practice is to set values inside the constructor because it allows for dependency injection and makes modifying the constructor to use an argument trivially easy.
If you are going to create a lot of World, i suggest creating an Abstract base that implements the ChunckManager.
That way you can leverage the use of base class, promote code reuse. You can also make your ChunkManager singleton since it only needs to be used by the base, and then use a method to actually instantiate the ChunkManager if you need specific properties from maps.
Use DI to pass the prop from child to base to instantiation of the ChunkManager
yes you can use one class type in another class its like one of filed on this class like when you use string a=new string() you use an object of class string its normal code

Class extending - best practice/best solution

First thing to note - I KNOW DELEGATION AND DECORATOR PATTERNS!
Second - I am using C# .NET 4.0, so if you come up with a solution that is specific for it, that's fine. But if solution will work for any OOP language and platform, that would be great.
And here the question goes...
I have a partial class (lets name it Class1), which I cannot modify. Thus, I can just extend it or/and inherit from it. This class provides a perfect data model for me, the only thing I need is to add some attributes to its properties (for validation, defining label text value in MVC etc - for now, I do not need answers like 'you can do what you need without attributes', that's not the matter of my question).
It is not a problem to use another class as a data model, so I can, say, create Class2 : Class1 and use Class2 as a model. Properties that need attributes would be defined as public new <type> <propertyname>. This will limit me to rewriting only the properties that need attributes, leaving all other untouched.
The smaller problem is that I do not what to redefine getters and setters for the properties, as all they gonna contain is return base.<propertyname> and base.<propertyname> = value, and if there are lots of such properties, this means lots of "stupid" coding. Is there a way to avoid this?
The bigger problem is that I have to parametrize my Class2 with Class1 instance and make something like class2.<propertyname> = class1.<propertyname> for each single property I have - too much of "stupid" coding. I can avoid it using reflection - find all properties with public getters and setters in Class1 and call prop.SetValue(child, prop.GetValue(parent, null), null); in the loop. This provides a generic function for simple cases, which is quite fine, as I mostly have simple models - lots of properties with public getters and setters without body and another logic. But I want more generic solution, and I do not like reflection. Any ideas?
Here goes the full code of the extension method that creates Class2 basing on Class1
public static Child ToExtendedChild<Parent, Child>(this Parent parent)
where Child : Parent, new()
{
Child child = new Child();
var props = typeof(Parent).GetProperties().Where(p => p.GetAccessors().Count() >= 2);
foreach (var prop in props)
{
prop.SetValue(child, prop.GetValue(parent, null), null);
}
return child;
}
(by the way, this method may not ideally implement my solution, so any corrections would also be appreciated)
Thanks in advance!
The smaller problem doesn't seem to be much of a problem. Maybe I'm misunderstanding the question, but assuming you're simply deriving a subclass, there should be no reason to redefine either the properties or their associated getters/setters.
The bigger problem might be resolved using something a little simpler. Using reflection for a lot of your object initialization seems a little expensive. If you're dealing with a class that is primarily a big bag or properties, maybe you should as if you need access to all of those properties in any given situation. You mention MVC and validation, is the entire model being used in the controller method you're validation is taking place in? If not, why not look at using a viewmodel that only exposes those pieces you need in that method?
Your reflection initializer is interesting, but if you're going to be doing a lot of this then you might consider investing a little time with Automapper. Otherwise maybe consider moving away from a generic solution to something that just tackles the problem at hand, i.e. mapping properties from an instance of an object to another instance of a derived object. Maybe you can create a copy constructor in the parent class and use that in your derived class?
public class Foo {
public string PropOne { get; set; }
public string PropTwo { get; set; }
public Foo(string propOne, string propTwo) {
PropOne = propOne;
PropTwo = propTwo;
}
public Foo(Foo foo) {
PropOne = foo.PropOne;
PropTwo = foo.PropTwo;
}
}
public class Pho : Foo {
// if you have additional properties then handle them here
// and let the base class take care of the rest.
public string PropThree { get; set; }
public Pho(string propOne, string propTwo, string propThree)
: base(propOne, propTwo) {
PropThree = propThree;
}
public Pho(Pho pho) : base(pho) {
PropThree = pho.PropThree;
}
// otherwise you can just rely on a copy constructor
// to handle the initialization.
public Pho(Foo foo) : base(foo) {}
}
I assume the partial class is generated code, it makes the most sense given your scenario.
I know of one way to do this, but depending on how the attribute gets crawled, it may not work.
// Generated Code
public partial Class1
{
public string Foo { get { ... } }
}
// Your Code
public interface IClass1
{
[MyAttribute]
public string Foo { get; }
}
public partial Class1 : IClass1
{
}
If someone were to look at attributes by using GetCustomAttributes with inheritance, then I think they would get this attribute.
As an aside, whenever I see generated code that doesn't have virtual properties it makes me cry a little bit inside.
To address your bigger question, why don't you just make Class2 a wrapper for Class1. Instead of copying all of the properties you can just give Class2 an instance of Class1 in the constructor, store it locally and make all of your properties pass-throughs. It means some hand coding, but if you're building a Class2 by hand anyway and want to decorate it with a bunch of attributes, well, you're hand coding Class2 anyway.

Categories