I got trouble when design class for my project. Currently, we developed 2 projects with the same structure but have some differences inside.
At project A, I have class ACore that includes class AConfiguration, AEquipmentManager. And I made an instance for object ACore that at everywhere in project, i can use: Acore.AConfiguration.XYZ (XYZ is method or property of AConfiguration class) or ACore.AEquipmentmanager.ABC(ABC is method or property of AEquipmentManager class)
At project B, I still have same structure with project A (BCore, BConfiguration, BEquipmentManager). But BConfiguration has different with AConfiguration (because each project has different configuration) and BEquipmentManager also has different with AEquipmentManager.
I want to reuse code for class ACore and BCore because they have the same code (Initialize EquipmentManager, Initialize Configuration, Dispose EquipmentManager, Dispose Configuration,...). Now, I want to write a library BaseCore that have the same structure with ACore and BCore (there are 2 class Configuration, EquipmentManager, same Intialize function, Dispose function), and with specific project (like A project, B project, or even C, D project later) i can use BaseCore library class (for reuse code) and just implement XEquipmentManager, XCofiguration depend on each project.
What is the best way I should design in this case? Thank for sharing your idea.
Regards,
Hoa Nguyen
I think you're on the right track,
But I would do it with interfaces:
Implement Core class that uses class that implements IConfigurable.
Make sure AConfiguration implements IConfigurable and all the
relevant methods.
Alternativly you can do something like that:
Implement Core class that uses Configuration class.
Implement AConfiguration/BConfiguration that inherits from
Configuration.
Reference A and B to the same Core class and that's it.
Hope it helps.
Does AConfiguration and BConfiguration have the same set of methods with different implementations or do the set methods also differ? If the set of methods are the same you could do it with interfaces. You could define an interface for configuration and equipmentamanager. Then you just BaseCore using these interface. Then you can supply the specific implementation in the construction of BaseCore Something like this (leaving out the singleton stuff)
interface IConfiguration
{
void somefunc();
}
interface IEquipmentManager
{
void someOtherFunc();
}
class BaseCore
{
private IConfiguration conf;
private IEquipmentmanager eq;
private BaseCore(){};
public BaseCore(IConfiguration inConf, IEquipmentmanager inEq) :
conf(inConf), eq(inEq)
{
conf.someFunc();
}
}
class AConfiguration : IConfiguration
{
public void someFunc()
{
do stuff!
}
public int intprop{get;set;}
}
class AEquipmentmanager : IEquipmentmanager
{
public void someOtherFunc()
{
do stuff!
}
}
Note you have to initialize an instance of AConfiguration and AEquipmentmanager. Before the construction of BaseCore like so
AConfiguration conf = new AConfiguration();
AEquipmentmanager eq = new AEquipmentmanager();
BaseCore base = new BaseCore(conf eq);
Alternatively you can simply create a BaseCore constructor that takes some enum to signify which implementation to you and then initialize an instance of the appropriate class in the BaseCore Constructor.
Alternatively you could possibly to it by implementing BaseCore with to Generic parameters and provide the the configuration and equipmentmanager implementation through these. You could still use the interfaces just the same but implement BaseCore with limits on the Generic arguments. BaseCore would look something like this:
class BaseCore<Configuration_type,Equipmentmanager_type>
where Configuration_type : IConfiguration, new()
where Equipmentmanager_type : IEquipmentmanager, new()
{
public Configuration_type Configuration {get;};
public Equipmentmanager_type Equipmentmanager {get;};
BaseCore()
{
Configuration = new Configuration_type();
Equipmentmanager = new Equipmentmanager_type();
}
}
This however puts the constraint on the types that they need a parameterless constructor. Initialization could supposedly be done afterwards though.
If you want to specialize your core for a specific configuration you can inherit from it like this
class Acore<Configuration_type,Equipmentmanager_type> :
BaseCore<Configuration_type,Equipmentmanager_type>
where Configuration_type : AConfiguration ,new()
where Equipmentmanager_type : AEquipmentmanager, new()
{
Acore() : base()
{
Configuration.intprop = 10;
}
}
Note that i added a property on AConfiguration that is not accessible in BaseCore but is in ACore
Related
I'm currently facing an issue for which I have found some partial solutions, but not the one that actually makes me believe I cannot do better.
So, to put in simple, I'm using the Dependency Injection, and I'm facing a circular reference error. Here's something similar to the code I am using.
First, I have a IMyBuilder interface:
public interface IMyBuilder { }
Then, I have an abstract class that implements the interface, and a bunch of class extending the abstract one:
public abstract class MyBuilderBase<DTO> : IMyBuilder
{
public abstract Dto GetDto();
}
public class UserBuilderDto : MyBuilderDto<UserDTO> { ... }
public class ProfessorBuilderDto : MyBuilderDto<ProfessorDTO> { ... }
public class AnimalBuilderDto : MyBuilderDto<AnimalDTO> { ... }
Then, I have a ProviderService, which helps me get the right IMyBuilder based on the DTO type. This ProviderServicedepends on ALL the IMyBuilder, like so:
public class ProviderService
{
private readonly IEnumerable<IMyBuilder> _builders;
public ProviderService(IEnumerable<IMyBuilder> builders)
{
_builders = builder;
}
public IMyBuilder GetBuilder<DTO>()
{
return _builders.OfType<MyBuilderBase<DTO>>().FirstOrDefault();
}
}
Finally, last piece of my code is the registration of the services, like so:
services.AddScoped<IMyBuilder, UserBuilderDto>();
services.AddScoped<IMyBuilder, ProfessorBuilderDto>();
services.AddScoped<IMyBuilder, AnimalBuilderDto>();
services.AddScoped<ProviderService>();
Notice that I register my builder as IMyBuilder: this way I can use the parameter IEnumerable<IMyBuilder> in the constructor of ProviderService.
Ok, now that we have all the inputs, here's the problem: inside the abstract method MyBuilderBase.GetDto I might need some other builder! Therefore, MyBuilderBase needs ProviderService, something like this:
public class AnimalBuilderDto : MyBuilderDto<AnimalDTO>
{
private readonly ProviderService _providerService;
public AnimalBuilderDto(ProviderService providerService)
=> (_providerService) = (providerService)
public AnimalDto GetDto()
{
// using _providerService
}
}
At this point you can clearly see where is my problem:
ProviderService requires AnimalBuilderDto
AnimalBuilderDto requires ProviderService
ProviderService requires AnimalBuilderDto
...
Circular dependency, thus my application crashes.
So, I've investigated this for a while, and I've come up with these solutions.
LAZY INITIALIZATION IN PROVIDER SERVICE
This would be something like here: https://thomaslevesque.com/2020/03/18/lazily-resolving-services-to-fix-circular-dependencies-in-net-core/
Basically, in the constructor of ProviderService I would not directly need to initialize the single IBuilderDto, avoiding the circular dependency..
What I don't like is that it seems a workaround, and not a solution. Also, if by any chance I put a breakpoint into providerService constructor, and inspect the lazy property, the application crashes.. Yeah, workaround.
METHOD INJECTION
I would need to change the signature of the abstract method as follow:
public abstract Dto GetDto(ProviderService providerService);
This way, I would not need the AnimalBuilderDto to depends on ProviderService, REMOVING the circular dependency.
This solution seems a real solution (it removes the circular dependency), but it adds a cost, which is the need of bringing this instance of ProviderService along all the application in order to use it when calling GetDto.
Here's end my investigation. Though, both solution does not seems to fix my problem! Ok, the second one does actually fix the problem, but create another one, which is the need of bringing the instance across all method calls.
Question is: is there any better solution to make a provider class like my ProviderService being reusable inside the same classes that it exploses?
Here's a quick and dirty way to break the circular reference, using an open generic service locator factory.
public interface IMyBuilder<TDTO>
{
TDTO GetDto();
}
public class BuilderFactory<TDTO>
{
private readonly IServiceProvider services;
public BuilderFactory(IServiceProvider services)
{
this.services = services;
}
public IMyBuilder<TDTO> GetBuilder() => services.GetRequiredService<IMyBuilder<TDTO>>();
}
public abstract class MyBuilderBase<DTO> : IMyBuilder<DTO>
{
public abstract DTO GetDto();
}
public class UserDTO { }
public class UserBuilderDto : MyBuilderBase<UserDTO>
{
private BuilderFactory<AnimalDTO> animalFactory;
public UserBuilderDto(BuilderFactory<AnimalDTO> animalFactory)
{
this.animalFactory = animalFactory;
}
public override UserDTO GetDto()
{
var animalBuilder = animalFactory.GetBuilder();
throw new NotImplementedException();
}
}
public class AnimalDTO { }
public class AnimalBuilderDto : MyBuilderBase<AnimalDTO>
{
private BuilderFactory<UserDTO> userFactory;
public AnimalBuilderDto(BuilderFactory<UserDTO> userFactory)
{
this.userFactory = userFactory;
}
public override AnimalDTO GetDto()
{
var userBuilder = userFactory.GetBuilder();
throw new NotImplementedException();
}
}
services.AddScoped(typeof(BuilderFactory<>));
services.AddScoped<IMyBuilder<AnimalDTO>, AnimalBuilderDto>();
services.AddScoped<IMyBuilder<UserDTO>, UserBuilderDto>();
Create an event in consumer class and fire it , once fired make the server class return its current instance
If the Builders use functions from ProviderService that use the Builders too, creating a factory is a way to break the cycle (at least in terms of timing, because the instances of the Builders are created at a later point in time and not upon registration.
However, if the Builders use only functions from ProviderService that do not rely on the Builders themselves, one other option is to move the functionality that is used in GetDto into another class that can be injected into both the Builders and the ProviderService. This way, the circular dependency is removed and both classes still have access to the functionality.
Basically, from
ProviderService -> Builders -> ProviderService
to
ProviderService -> Builders -> SharedFunctions
-> SharedFunctions
Whether or not the Builders and the ProviderService use the same instance of SharedFunctions then depends on the scope that you register it in the IoC container.
In .NET 6 appeared new feature is DI by type anonymous delegate:
Questing:
I have many clases inherited from based class with constructor.
now I have to write such long initializations
Isn't there a way to get rid of this writing?, for example, like this (psevdocode)
This is how parameter binding in minimal APIs (introduced in .NET 6) works and this is handled by the framework (ASP.NET Core). But it is not completely new idea and it is not bound to the anonymous labmdas - injection in controllers actions via FromServicesAttribute is present from the first ASP.NET Core (see the applies to section) version.
As for tackling the parameter injection into the base class issue - one way around would be just creating class holding those parameters, register it in DI and injecting it. Something like this:
public class BaseClassParameters
{
public BaseClassParameters (A a, B b, ...) {A = a; ...}
public A A { get; }
...
}
public class BaseClass
{
public BaseClass(BaseClassParameters p) { // copy from p}
}
public class ChildClass : BaseClass
{
public ChildClass(BaseClassParameters p): base(p) // can create ChildClassParameters : BaseClassParameters if needed or just add deps on this level
{
}
}
services.AddTransient<BaseClassParameters>(); // or use needed lifetime for class hierarchy here
I'm having trouble with getting generics and DI to work together in an MVC Core project. I have a generic class (this is just a fragment). I need to initialize Input and Output because of how these are used in other parts of the code, so I'm using Activator to provide initial values and the new() constraint.
public class Message<TIn, TOut> :
where TIn : class, IMessagePart, new()
where TOut : class, IMessagePart, new() {
public Message(){}
public Message(TIn inpart, TOut outpart) {
Input = inpart;
Output = outpart;
}
public TIn Input { get; set; } = (TIn)Activator.CreateInstance(typeof(TIn));
public TOut Output { get; set; } = (TOut)Activator.CreateInstance(typeof(TOut));
}
I have other classes that are used by this, and they have some static utility classes. I'm trying to replace these static classes using DI.
public class Project : IMessagePart{
int y = 1;
var x = StaticUtilityClass.StaticMethod(y);
}
is used like this
var projectMessage = new Message<Project, Project>();
I'm converting the static utility classes to instance classes and injecting them. I'm using the built-in .Net core container. I converted the utilities to instance classes and registered them as concrete singletons in the container. For most things I can just do the normal-
public class SomeClass{
private readonly UtilityClass _utility;
public SomeClass(UtilityClass utility){
_utility = utility;
var x = _utility.Method(1);
}
Things work fine until I get to the generics. I can't do constructor injection on projectMessage, because the generic needs to new it up and it has the new() constraint, so I need a parameterless constructor. If I add just the an injecting constructor I get
'Project' must be a non-abstract type with a public parameterless
constructor in order to use it as parameter 'TIn' in the generic type
or method 'Message'.
and if I add both constructors Activator is only going to call the one without parameters, so DI isn't invoked. I tried using the overload of CreateInstance a few different ways, but no luck tricking it.
Any suggestions here? I don't know if I should stay with statics, try some sort of service locator approach, or if there is a different way to writing the generic.
The answer to why you are getting the error you're seeing is the new() constraints. That specifies that the parameter must have a public parameterless constructor. Which is exactly what your error says. Removing that constraint should fix that error. However, you still have another issue if you want to use DI.
Aside from IMessagePart none of your classes have backing interfaces. In order to use DI effectively you need to define an IMessage, IProject etc. Then your container can create specific instances at runtime, rather than using the Activators like you are now. So your Message declaration would look like:
public class Message<TIn, TOut> : IMessage,
where TIn : class, IMessagePart
where TOut : class, IMessagePart
{
public TIn input { get; set; }
public TOut output { get; set; }
public Message(TIn inpart, TOut outpart) {
this.input = inpart;
this.output = outpart;
}
}
You would setup your DI container something like:
public Startup()
{
var container = new DiContainer(); // I know this is the wrong name; I'm not familiar with the built in container naming and functionality.
container.Register<IMessage>();
container.Register<IMessagePart>();
container.Register<IProject>();
// Register other stuff here
}
Change the syntax there for your specific container. You also have the option of registering your instances something like:
container.Register<Message>(() => Message(part1, part2));
so that you specifically inject a Message that is newed up at Startup time, but that's not really ideal in most cases. Usually you want your DI container to dynamically create an instance as needed (hence the interfaces), rather than using a single concrete instantiation. There are exceptions of course; a SQL connection is one common one.
I am getting confused with the scenario of 2 classes implementing the same interface and Dependency Injection.
public interface ISomething
{
void DoSomething();
}
public class SomethingA : ISomething
{
public void DoSomething()
{
}
}
public class SomethingAB : ISomething
{
public void DoSomething()
{
}
}
public class Different
{
private ISomething ThisSomething;
public Different(ISomething Something)
{
ThisSomething = Something;
}
}
I have seen online examples say that this is valid but you would only use one class at a time. So if the app is running at SiteA you tell your IOC to use SomethingA but if its at SiteB you tell it to use SomethingAB.
Is it considered bad practice therefore to have one app that has 2 classes that implement 1 interface and for it to try to use both classes? If its not how do you tell the IOC which class to use in the relevant circumstance?
UPDATE: To explain it better I will use Ninject's example:
public class Samurai
{
private IWeapon Weapon;
public Samurai(IWeapon weapon)
{
this.Weapon = weapon;
}
}
public class Sword : IWeapon
{
...
}
public class Gun : IWeapon
{
...
}
public class WarriorModule : NinjectModule
{
public override void Load()
{
this.Bind<IWeapon>().To<Sword>();
this.Bind<IWeapon>().To<Gun>(); //Just an example
}
}
So now you have 2 classes that use IWeapon. Depending on something or a context in your app you want Samurai to have a Sword sometimes or a Gun at other points. How do you make this happen? How do you handle that "if" scenario??
I don't think that this is a bad practice in the general case. There are situations where you could need different implementations of the same interface inside the same application and based on the context use one or another implementation
As far as how to configure your DI to enable this scenario, well, it will depend on your DI of course :-) Some might not support it, others might not, others might partially support it, etc..
For example with Ninject, you could have the following classes:
public interface ISomething
{
}
public class SomethingA : ISomething
{
}
public class SomethingB : ISomething
{
}
public class Foo
{
public Foo(ISomething something)
{
Console.WriteLine(something);
}
}
public class Bar
{
public Bar(ISomething something)
{
Console.WriteLine(something);
}
}
and then use named bindings when configuring the kernel:
// We create the kernel that will be used to provide instances when required
var kernel = new StandardKernel();
// Declare 2 named implementations of the same interface
kernel.Bind<ISomething>().To<SomethingA>().Named("somethingA");
kernel.Bind<ISomething>().To<SomethingB>().Named("somethingB");
// inject SomethingA into Foo's constructor
kernel.Bind<Foo>().ToSelf().WithConstructorArgument(
"something", ctx => ctx.Kernel.Get<ISomething>("somethingA")
);
// inject SomethingB into Bar's constructor
kernel.Bind<Bar>().ToSelf().WithConstructorArgument(
"something", ctx => ctx.Kernel.Get<ISomething>("somethingB")
);
Now when you request an instance of Foo it will inject SomethingA into it its constructor and when you request an instance of Bar it will inject SomethingB into it:
var foo = kernel.Get<Foo>();
var bar = kernel.Get<Bar>();
i worked with Unity and spring in this context and i think that interest lies in having a weak coupling between packages, ie classes, the ability to change service or point of entry is a consequence of the ioc.
ioc provides flexibility in the use of service, or from the time the services implement the same interface,
If Utilize Service A Service B and Service is in the service package A and package B is in B.
Package A has no reference on the package b, but the service A has a reference on the package containing the interfaces.
Therefore we conclude that we have a weak coupling between package A and package b.
Having multiple implementations mapped to the same interface isn't really bad practice, but it isn't he most common usage pattern.
You didn't specify a specific DI tool, but if you use Unity, you can do this with named instances. See here: Unity - how to use multiple mappings for the same type and inject into an object
I have many classes in a project that need to all have a base set of the same constructors and 1 public method. Below is an example of this partial class:
public partial class SHIPMENT_LINE
{
private OracleConnection _rp = null;
private EntityConnection _rpe = null;
private static string _schema = "";
public SHIPMENT_LINE() { }
public SHIPMENT_LINE(BHLibrary.Configuration.ConnectionOption Environment)
{
SetConnection(Environment);
}
public void SetConnection(BHLibrary.Configuration.ConnectionOption Environment)
{
this._rp = Configuration.RPConnection(Environment);
this._rpe = Configuration.RPEntityConnection(Environment, out _schema);
}
}
I need to implement the same private variables, constructors, and the SetConnection method on each of my classes that I create. After this all exists in each class, then each class will do something different, so the classes are not all necessarily related, aside from the fact that they all have this same "Beginning."
How should I go about building each of these classes so that I do not have to implement this SetConnection method in each of the classes that I create?
Keep this in mind:
Due to other restrictions, I cannot inherit from another class in any of these classes. I can, however, use Interfaces if necessary.
I would suggest going for composition rather than inheritance...
Make each of the class implement an interface, then have another class (not related to these) which also implements the interface and has a concrete implementation of it. All the classes you've mentioned above should have an instance of this additional class and just call through to it.
Example
public partial class SHIPMENT_LINE : ISetConnection
{
private ConnectionSetter connector = new ConnectionSetter();
public void SetConnection(BHLibrary.Configuration.ConnectionOption Environment)
{
this.connector.SetConnection(Environment);
}
}
public class ConnectionSetter : ISetConnection
{
public void SetConnection(BHLibrary.Configuration.ConnectionOption Environment)
{
// Implementation
}
}
If you can't subclass then an abstract class is not a viable solution and interfaces are only going to give you the contract that your common classes conform to without any implementation.
I would suggest implementing the common functionality in a common class and using this as a private member in your other classes (I.E. composition rather than inheritance). Your other classes could all implement an interface to ensure they all have the same methods and they could just forward their calls onto the private classes implementation of the method.
E.G.
private MYClassWithCommonFunctionality xyz = new MYClassWithCommonFunctionality();
And then...
Private void MyCommonInterfaceMethod(object param)
{
// Do derived class specific stuff here...
xyz.MyCommonInterfaceMethod(param);
}
And as an added bonus and a bit of forward thinking....have the common class also share the same interface and pass an implementation of this into your other classes constructor. That way in the future you can swap the implementation for another.
If you cannot create a base class that will implement your common functionality (any reason why?) than you probably can use T4 template to generate partial class with your common methods.