Constructor injection with non-dependency parameters - c#

I have an interface ITradingApi like so:
public interface ITradingApi
{
IOrder CreateOrder(...);
IEnumerable<Symbol> GetAllSymbols();
// ...
}
This is meant to be a facade for the different APIs of the vendors of trading software.
My view model has a dependency on this trading API in its constructor:
public class MainViewModel
{
public MainViewModel(ITradingApi tradingApi) { /* ... */ }
// ...
}
I use Ninject as an IoC container, so I will create an instance of my view model like this:
var vm = kernel.Get<MainViewModel>();
Now, my problem:
The implementation of ITradingApi might need additional parameters to work.
Example:
One vendors API uses TCP/IP internally, so I need a hostname and a port.
Another vendor uses a COM object. Here I don't need any info.
A third vendor needs username and password of the account.
In the spirit of not allowing incomplete objects, I added these as parameters to the constructors of the concrete implementations.
Now, I am not sure, how this would work. Clearly, these additional parameters do not belong into the interface, because they are specific to each implementation.
On the other hand, these additional parameters need to be entered by the end-user and then passed to the implementation of ITradingApi, meaning that the user of ITradingApi needs intimate knowledge about the concrete implementation.
How to solve this dilemma?
UPDATE:
One approach could be to create an ITradingApiProvider that exposes a list of required parameters. The View could automatically create an input form for these parameters that is databound to the parameters in ITradingApiProvider. Now, when an ITradingApi instance is requested from the provider, it can make use of these parameters to create an instance of the concrete implementation. Clearly the implementation of ITradingApiProvider and ITradingApi are tightly coupled, but I think that is not a problem as long as each implementation of ITradingApi comes with a corresponding implementation of ITradingApiProvider.

Based on the information so far put forth here, I'd like to point out one or two things:
First of all, whether or not the concrete configuration values are supplied at composition time or truly first available at runtime as user input makes a huge difference. As long as they can be resolved at composition time things are easy because you can simply read the values from the environment and supply them to the appropriate constructors. So, for the rest of this answer I'm going to assume that things are much harder and you actually need to get those values from the user at runtime.
Instead of attempting to come up with a general-purpose configuration API I'd much rather model what's actually going on. In this case it sounds to me like we're collecting configuration values from the user, so why not model this explicitly?
Product Trader
Define an interface like this:
public interface ITradingApiTrader
{
ITradingApi Create(Type apiType);
}
Here, it's assumed that apiType can cast to ITradingApi, but this can't be enforced by the compiler. (The reason I'm calling this a 'Trader' is because this is a variation of the Product Trader pattern (PLoPD 3).)
How is this different than before?
Well, you can implement the Create method by showing a user interface for each type of ITradingApi. Each concrete user interface gathers the values required for its own concrete ITradingApi implementation and subsequently returns a correctly configured instance.
If you know the concrete types at compile time, other variations include these:
public interface ITradingApiTrader
{
ITradingApi CreateMT4TradingApi();
ITradingApi CreateFooTradingApi();
ITradingApi CreateBarTradingApi();
// etc.
}
Perhaps you can also do this (although I haven't tried to compile this):
public interface ITradingApiTrader
{
ITradingApi Create<T>() where T : ITradingApi;
}
Note also that you don't need to define the first ITradingApiTrader's Create method based on a Type - any identifier (such as an enum or string) might do instead.
Visitor
If the set of ITradingApi is (finite and) known at design time, the Visitor design pattern might also offer an alternative.
If you use a Visitor, you can make the Visit method show an appropriate user interface and then subsequently use the values collected from the user interface to create the appropriate ITradingApi instance.
Basically this is just a variation on the previous 'solution' where the Product Trader is implemented as a Visitor.

Is this what your after?
ninjectKernel.Get<MainViewModel>().WithConstructorArgument("tradingApi",
kernel.Get<ITaxCalculator>() .WithConstructorArgument("additionalParameter","someValue")));

Ok my two cents, I am not sure of anything you know. It is just to help and try...
We give a visitor to your api as construction of the interface:
public interface ITradingApi
{
Object CreateOrder();
IEnumerable<Object> GetAllSymbols();
}
public class TradingApi : ITradingApi
{
IvisitorAPI _VisitorAPI;
public TradingApi(IvisitorAPI visitorAPI)
{
_VisitorAPI = visitorAPI;
}
public Object CreateOrder()
{
var Order = new Object();
//bla bla bla
//here code relative to different visitor
_VisitorAPI.SaveOrder(Order);
return Order;
}
}
It is your visitor that knows how to handle some of the action, because depending on the visitor he will use your api in different ways to achieve the same action ( here SaveOrder).
public interface IvisitorAPI
{
bool SaveOrder(Object order);
}
public class visitorApiIP : IvisitorAPI
{
public string HostName { get; set; }
public int Port { get; set; }
public visitorApiIP(string hostname, int port)
{
HostName = hostname;
Port = port;
}
public bool SaveOrder(Object order)
{
//save the order using hostname and ip
//...
//....
return true;
}
}
Only the visitor has a knowledge of what he needs to achieve his version of the action.
Therefore it is not the APi that needs additionnal parameters, we are pushing the logic away in the visitor class.
This visitor class might be created only when ewe know who is the visitor therefore, surely at runtime
Hope it might give you some perspective. I do not know if the whole theory can be applied your exact situation.
My best anyway ;)

The solution is to use the approach as outlined in the update part of my question. ITradingApiProvider takes the role of an abstract factory and thus should be renamed to ITradingApiFactory. It would expose a list of needed parameters whose values can be set. This list in turn can be used by the View to automatically present the user with an input form to enter a value for each parameter, because only the user knows the values of for the parameters.
The call to Create would then use these parameters:
public interface ITradingApiFactory
{
ITradingApi Create();
IEnumerable<Parameter> Parameters { get; }
}
public class Parameter
{
public Parameter(Type type, string name, string description)
{ Type = type; Name = name; Description = description; }
public Type Type { get; private set; }
public string Name { get; private set; }
public string Description { get; private set; }
public object Value { get; set; }
}
public class MT4TradingApiFactory : ITradingApiFactory
{
Dictionary<string, Parameter> _parameters;
public MT4TradingApiFactory()
{ /* init _parameters */ }
public ITradingApi Create()
{
return new MT4TradingApi(_parameters["hostname"].ToString(),
(int)_parameters["port"]);
}
IEnumerable<Parameter> Parameters { get { return _parameters.Values; } }
}
More info can be found in this answer.
This can be advanced further to make it easier to use, by giving each Factory implementation the parameters as properties and change the Parameter class to work directly on these properties using expression trees. If someone is interested in this advanced factory design, please leave a comment.

I think there is nothing wrong with your provider approach. You have two concerns here:
An operational one: your ITradingAPI which defines a contract for operations you can perform.
A meta-data one: something which describes properties of an actual implementation (meta data might not be quiet right but can't think of a better name for it)
Now apparently you need something which can make the connection between the two and that is your ITradingAPIProvider. Seems reasonable straight forward and has good chance of that you will still understand your code when coming back to it after a year ot two ;)

How about trying something similar to the strategy pattern? Create a new interface called IConnectStrategy:
interface IConnectStrategy
{
void Connect();
}
Add the connectstrategy as an argument to the method void CreateOrder(IConnectStrategy connectStrategy) in ITradingApi and let each vendor create/specify their own method for connecting. E.g. for one vendor create:
public class TCPConnectStrategy : IConnectStrategy
{
public TCPConnectStrategy(string hostName, int port)
{
/* ... */
}
public void Connect()
{
/* ... tcp connect ... */
}
}
(Connect might not be the best name or even what you are actually doing, but please apply it to whatever works for your project.)
Edit after comments:
Create a strategy that only have contracts for each method that have vendor-specific parameters. Then add a method void SetVendorStrategy(IVendorStrategy vendorStrategy) (or a property) to the ITradingAPI-interface. Each implementation of the strategy has their own constructor with their own parameters, and each method (that require vendor specific parameters) in each implementation of the ITradingAPI-interface simply calls vendorStrategy.DoSomethingWithVendorSpecificData().

Related

Locate different generic services in one non generic Locator

I have various Services that implement
public interface IReceiver<PayLoad>
{
string Name {get;}
Task SendObjectContainerAsync(ObjectContainer<PayLoad> m);
Task<ObjectContainer<PayLoad>> GetSnapshot();
}
For Example
public class Printer : IReceiver<TextDocument>
or
public class TextDocumentService : IReceiver<Letter>
Now I want to collect all instances of each IReceiver in one Controller, I could
public class Broker<Payload>
{
List<IReceiver<Payload>> receivers;
}
and initialize an Instance for each type of IReceiver and then DI it into the IReceivers to enable them to register and get the Instances from other places.
Is this a good way to handle different Services? I think it gets kind of messy with many Brokers and I would rather have something like
static void register<Payload>(IReceiver<Payload> RegisterMe)
and
static List<IReceiver<Payload>> getReceivers<PayLoad>()
But im not able to implement this Locator because I dont know how to administrate different generic Lists in one non generic class
Any Suggestions?
Using a Dependency Injection framework you should be able to configure which receivers you want to particulary inject into specific Broker<PayLoad> instances.
In the other hand, you should practice constructor injection:
public class Broker<Payload>
{
public Broker(IList<IReceiver<PayLoad>> receivers)
{
Receivers = receivers;
}
public IList<IReceiver<PayLoad>> { get; }
}
Now, the next issue is that you want a broker to handle more than a receiver type. So the easiest way will be a small refactor on your IReceiver<PayLoad> interface:
// No more PayLoad generic type parameter! Let's move it to
// the methods
public interface IReceiver
{
string Name { get; }
Task SendObjectContainerAsync<TPayLoad>(ObjectContainer<TPayLoad> m);
Task<ObjectContainer<TPayLoad>> GetSnapshot<TPayLoad>();
}
Finally, your brokers will look as follows:
public class Broker
{
public Broker(IList<IReceiver> receivers)
{
Receivers = receivers;
}
public IList<IReceiver> { get; }
}
About the Locator thing
Are you going to implement a static service locator? Don't do this, it's considered an anti-pattern, because you're going to couple your components to how they receive their dependencies while you should avoid this.
Components should remain agnostic on how they get their dependencies, because this is a reponsibility of a higher layer, usually the IoC/DI container.
Also, it makes your code more test-friendly, because you can test your components without integrating the IoC/DI container, because you just expect constructor arguments.

How do I wire an IoC Container to pass a value to a factory method to resolve?

Background / Goal
We have several "client sites" on our web app that users can switch between
We do a lot of wiring up of objects based on factories that take in the client site ID and create an instance
I would like to inject these dependencies into the classes instead
I also want to make sure I can pass in my own implementations to the constructor for the purposes of unit testing.
We have initially elected to use StructureMap 3.x to do so, but are open to alternatives if they can help us solve this scenario gracefully.
Question
In instances where I require a different dependency based on a client site ID that I'll only get at run-time, what is the appropriate way to set up an IoC container and the appropriate way to request the object from it in order to make it as painless as possible?
Am I thinking about this wrong and unintentionally creating some sort of anti-pattern?
Example Code
Normally we're doing something like the following coming in:
public class MyService
{ DependentObject _dependentObject;
public MyService(int clientSiteID)
{
// ...
_dependentObject = new dependentObjectFactory(clientSiteID).GetDependentObject();
}
public void DoAThing()
{
//...
_dependentObject.DoSomething();
}
}
What I'd like to do:
public class MyService
{ DependentObject _dependentObject;
public MyService(int clientSiteID)
{
// ...
_dependentObject = MyTypeResolver.GetWIthClientContext<IDependentObject>(clientSiteID);
}
public MyService(int clientSiteID, IDependentObject dependentObject)
{
// ...
_dependentObject = dependentObject;
}
public void DoAThing()
{
//...
_dependentObject.DoSomething();
}
}
I would set up the IoC container in such a way that I can use my MyTypeResolver to pass in the clientSiteID, and have the container call my DependentObjectFactory and return the correct object result.
I'm new to IoC containers, and while I'm trying to plow through the literature, I have the feeling it may be easier than I'm making it so I'm asking here.
Probably the simplest way to do this is to use an Abstract Factory. Most IOC frameworks can auto-create them for you, but here's how you can do it manually (I always prefer to do it manually first so I know it works, and then you can check out how the framework can help you automagic it)
Now one thing to mention - I would recommend a slight readjustment of how the final solution works, but I'll go into that once I have shown how it can currently work. Example below assumes Ninject and please excuse any typos, etc.
First create an interface for your dependency
public interface IDependentObject
{
void DoSomething();
}
Then declare empty marker interfaces for each specific implementation of IDependentObject
public interface INormalDependentObject:IDependentObject{};
public interface ISpecialDependentObject:IDependentObject{}
and implement them:
public class NormalDependentObject:INormalDependentObject
{
readonly int _clientID;
public DependentObject(int clientID)
{
_clientID=clientID;
}
public void DoSomething(){//do something}
}
public class DependentObject:ISpecialDependentObject
{
readonly int _clientID;
public DependentObject(int clientID)
{
_clientID=clientID;
}
public void DoSomething(){//do something really special}
}
and of course as you mentioned you may have many more implementations of IDependentObject.
There may be a more elegant way of allowing your IOC framework to resolve at runtime without having to declare the marker interfaces; but for now I find it useful to use them as it makes the binding declarations easy to read :)
Next, declare an interface and implementation of an IDependentObjectFactory:
public interface IDependentObjectFactory
{
IDependentObject GetDependenObject(int clientID);
}
public class DependentObjectFactory: IDependentObjectFactory
{
readonly _kernel kernel;
public DependentObjectFactory(IKernel kernel)
{
_kernel=kernel;
}
public IDependentObject GetDependenObject(int clientID)
{
//use whatever logic here to decide what specific IDependentObject you need to use.
if (clientID==100)
{
return _kernel.Get<ISpecialDependantObject>(
new ConstructorArgument("clientID", clientID));
}
else
{
return _kernel.Get<INormalDependentObject>(
new ConstructorArgument("clientID", clientID));
}
}
}
Wire these up in your Composition Root:
_kernel.Bind<INormalDependentObject>().To<NormalDependentObject>();
_kernel.Bind<ISpecialDependentObject>().To<SpecialDependentObject>();
_kernel.Bind<IDependentObjectFactory>().To<DependentObjectFactory>();
and finally inject your factory into the service class:
public class MyService
{
IDependentObject _dependentObject;
readonly IDependentObjectFactory _factory;
//in general, when using DI, you should only have a single constructor on your injectable classes. Otherwise, you are at the mercy of the framework as to which signature it will pick if there is ever any ambiguity; most all of the common frameworks will make different decisions!
public MyService(IDependentObjectFactory factory)
{
_factory=factory;
}
public void DoAThing(int clientID)
{
var dependent _factory.GetDependentObject(clientID);
dependent.DoSomething();
}
}
Suggested changes
One immediate change from your structure above is that I have left clientID out of the service constructor and moved it to a method argument of DoAThing; this is because it makes a bit more sense to me that the Service itself would be stateless; of course depending on your scenario, you may want to not do that.
I mentioned that I had a slight adjustment to suggest , and it's this; the solution above depends (no pun!) on implementations of IDependentObject having a constructor with this signature:
public SomeDependency(int clientID)
If they don't have that signature then the factory won't work; personally I don't like my DI to have to know anything about constructor params because it takes you out of purely dealing with interfaces and forcing you to implement specific ctor signatures on your concrete classes.
It also means that you can't reliably make your IDependentObjects be part of the whole DI process (i.e whereby they themselves have dependency graphs that you want the framework to resolve) because of the forced ctor signature.
For that reason I'd recommend that IDependentObject.DoSomething() itself be changed to DoSomething(int clientID) so that you can elide the new ConstructorArgument part of the factory code; this means that your IDependentObject s can now all have totally different ctor signatures, meaning they can have different dependencies if needs be. Of course this is just my opinion, and you will know what works best in your specific scenario.
Hope that helps.

Unity constructor injection with implied names

I am trying to inject two classes into my constructor, the problem they are both of the same interface. My registering is:
container.RegisterType<ITrackerSection, ScopeSection>();
container.RegisterType<ITrackerSection, SampleSection>();
As you can see they are both of type ITrackerSection but have different implementations. My constructor looks as follows:
public TrackerEngine(ITrackerSection scopeSection, ITrackerSection sampleSection)
Both these parameters are injected as a sampleSection as it was last to be registered for the interface type. I have no problem with naming the registered types for example
container.RegisterType<ITrackerSection, ScopeSection>("scopeSection");
container.RegisterType<ITrackerSection, SampleSection>("sampleSection");
But this now means I have to specify the classes parameters and that seems messy and adding dependency when unity is more than capable of resolving them. Furthermore the registering of the TrackerEngine would also need to specify the parameters. I know I could use an in line attribute in the constructor of TrackerEngine but I would prefer Unity to infer the objects by the names.
Can Unity (I can not seem to get this working) correctly inject the correct implementation of the interface purely from the name given to the parameter in the constructor? So ITrackerSection scopeSection is the same name given in the registering of ScopeSection so use that type.
I agree with the comments regarding sharing the interface. The whole point of IOC is that your engine should not need to know which implementation to use. It should only be given the interface.
A way to solve this is to allow Unity to inject an array of interfaces:
public TrackerEngine(ITrackerSection[] trackerSections) { }
This way you can inject both. But then, if you really need to know which interface is which, you could implement a enum or something in your interface. Something like this:
public interface ITrackerSection {
SectionType Section { get; }
}
public enum SectionType{
0 = Scope,
1 = Sample
}
And in your implementation:
public class ScopeTrackerSection : ITrackerSection {
// Do your stuff...
public SectionType Section {
get { return SectionType.Scope; }
}
}
public class SampleTrackerSection : ITrackerSection {
// Do your stuff...
public SectionType Section {
get { return SectionType.Sample; }
}
}
And in your Engine, you can fetch the interface needed to the desired action.
public TrackerEngine(ITrackerSection[] trackerSections) {
var scopeTrackerSection = trackerSections.FirstOfDefault(x => x.Section == SectionType.Sample);
// Do something with scopeTrackerSection
}

When should I use params Object[] versus Dictionary<String, Object>?

I'm defining an API as an interface which we'll call IFoo and I want to define a method Bar()
This method Bar() will take one required argument and then some arbitrary number of other arguments. The interpretation of these other arguments will be up to implementors of IFoo
For this scenario is it more appropriate to define my interface using params or using Dictionary<String, Object> e.g.
public interface IFoo
{
bool Bar(String id, params Object[] params);
}
Or
public interface IFoo
{
bool Bar(String id, Dictionary<String, Object> params);
}
It seems like the former is easier for users to invoke but the latter is more explicit in its intentions since with the former you'd have to specify the parameters in a specific order for the implementation to interpret them properly while with the latter you are essentially doing named parameters.
So questions:
Which form should I be using (and why?) - is one of these considered best practice over another?
Are there specific advantages to one style versus the other that I should be aware of? Is one of these considered a code smell?
Is there an alternative pattern that would achieve the same thing in a different/nicer way?
For the record I am aware of named parameters in .Net 4.0 but this code needs to be compilable on .Net 3.5 so can't use any .Net 4.0+ functionality
Edit
Just to add more detail on what my IFoo and Bar() methods are actually representing because someone asked.
IFoo represents some storage subsystem and Bar() is actually a create operation. Depending on the storage subsystem Bar() could require no parameters other than the ID or it could require many parameters.
Edit 2
So in response to #Kirk Woll's comment and #Fernando's answers here's more information.
I will likely never invoke IFoo.Bar() myself, this interface is part of an open source framework. 3rd party devs will be implementing IFoo and end users will be invoking specific instances of it, the point of having IFoo at all is to make it easier for users to migrate their applications between storage subsystems because they can code to interfaces rather than specific implementations as far as humanly possible.
In the simplest case the underlying storage subsystem only has one form of store so no parameters will be required other then the ID. In the complex case the storage subsystem may allow multiple types of store and each type of store may permit arbitrarily complex set of configuration parameters e.g. index size, persistence, transaction behavior, indexing strategy, security and ACL considerations etc.
I agree with #Fernando that maybe something more polymorphic may make sense, maybe polymorphism combined with generics and type restrictions may be best e.g.
public interface IFoo
{
bool Bar<T>(T parameters) where T : IBarConfig;
}
public interface IBarConfig
{
String ID { get; set; }
}
Then with an implementation like so:
public class MyFoo
{
bool Bar<T>(T config) where T : MyBarConfig
{
//Implementation
}
}
public class MyBarConfig : IBarConfig
{
public String ID { get; set; }
public long IndexSegmentSize { get; set; }
//Etc...
}
This is off the top of my head so not sure if it is actually legal to define Bar() in MyFoo with a different type restriction then the interface it implements?
You need to decide if you need to search or be able to retrieve an Object from the params collection/Array.
When using Object[] params, There is no indexing on the Objects. You need to iterate the whole collection to find an item (by its key).
When using a Dictionary<String, Object>, your Objects are indexed by their key, and its always easy to search/query by the key.
Depending on your need, you need to decide your Approach.
Dictionary is faster for searches, but there is an overhead to create the indexes.
The dictionary approach has another problem: typos. You'll probably need to define a lot of constants to use as keys to avoid this problem.
Why not going for a polymorphic solution?
public interface IFoo {
void Bar(FooData data);
}
public abstract class FooData {
public int Id {get;set;}
}
public class MyFooData1 : FooData {
public string SomeProperty {get;set;}
//...
}
public class MyFoo : IFoo {
public void Bar(FooData data) {
var myData = (MyFooData1)data;
//...
}
}
public class MyFooData2 : FooData {
public int SomeOtherProperty {get;set;}
//...
}
public class MyFoo2 : IFoo {
public void Bar(FooData data) {
var myData = (MyFooData2)data;
//...
}
}
You'll end up with more smaller classes, but they are easy to test and extend.
Update
#RobV you can't change the type restriction if you're implementing an interface, but, if you put your type parameter at the interface declaration, you may accomplish what you're trying to do:
public interface IFoo<T> where T : IBarConfig {
void Bar(T parameters);
}
public class MyBarConfig: IBarConfig {
public String ID { get; set; }
public long IndexSegmentSize { get; set; }
}
public class MyFoo : IFoo<MyBarConfig> {
public void Bar(MyBarConfig config) {
//Implementation
}
}
params provide easier to write/read code compared to Dictionary if you need to write them inline. I.e. imaging constructing dictionary for every call to String.Format - code will be unreadable. On other hand if you already have dictionary of parameter - ok to use it.
I would recommend to reconsider API and see if you can accept IEnumerable, or even better IEnumerable<T> as arguments. Unfortunately with such generic IFoo name of sample it is not possible to see if such approach would work.
Which form should I be using (and why?) - is one of these considered best practice over another? ---> You should use the second one, because it's a lot less error prone than the second one.
Regarding the alternative pattern, there is surely a way to implement this in a nicer way. Can you tell us what your problem actually is? instead of using IFoo and Bar? I can't suggest anything else unless I know exactly what you are trying to do, and why...
The fact that you mention optional parameters makes me think the IDictionary<string,object> approach would be better - that's your best approach to give that kind of interface in .Net 3.5. You could just ask for object and do something like what MVC does for htmlAttributes (using reflection to turn the anonymous object into an IDictionary<string,object>).
The scenario where I'd prefer the params object[] approach are ones where trying to give them names in every situation would just be weird/impossible, like for string.format.

Creating a Generic Save() Method for Models

I have a fairly simple system, and for the purposes of this question there are essentially three parts: Models, Repositories, Application Code.
At the core are the models. Let's use a simple contrived example:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
In that same project is a generic repository interface. At its simplest:
public interface IRepository<T>
{
T Save(T model);
}
Implementations of that interface are in a separate project and injected with StructureMap. For simplicity:
public class PersonRepository : IRepository<Person>
{
public Person Save(Person model)
{
throw new NotImplementedException("I got to the save method!");
// In the repository methods I would interact with the database, or
// potentially with some other service for data persistence. For
// now I'm just using LINQ to SQL to a single database, but in the
// future there will be more databases, external services, etc. all
// abstracted behind here.
}
}
So, in application code, if I wanted to save a model I would do this:
var rep = IoCFactory.Current.Container.GetInstance<IRepository<Person>>();
myPerson = rep.Save(myPerson);
Simple enough, but it feels like it could be automated a lot. That pattern holds throughout the application code, so what I'm looking to do is create a single generic Save() on all models which would just be a shorthand call to the above application code. That way one would need only call:
myPerson.Save();
But I can't seem to figure out a way to do it. Maybe it's deceptively simple and I'm just not looking at it from the correct angle. At first I tried creating an empty ISaveableModel<T> interface and intended to have each "save-able" model implement it, then for the single generic Save() method I would have an extension on the interface:
public static void Save<T>(this ISaveableModel<T> model)
{
var rep = IoCFactory.Current.Container.GetInstance<IRepository<T>>();
model = rep.Save(model);
}
But it tells me that rep.Save(model) has invalid arguments. It seems that it's not wiring up the type inference as I'd hoped it would. I tried a similar approach with a BaseModel<T> class from which models would inherit:
public class BaseModel<T>
{
public void Save()
{
this = IoCFactory.Current.Container.GetInstance<IRepository<T>>().Save(this);
}
}
But the compiler error is the same. Is there a way to achieve what I'm trying to achieve? I'm very flexible on the design, so if I'm going about something all wrong on an architectural level then I have room to step back and change the big picture.
Would a generic extension method solve it?
public static T Save<T>(this T current)
{
var rep = IoCFactory.Current.Container.GetInstance<IRepository<T>>();
rep.Save(current);
}
You can then constrain it to your ISaveableModel<T> interface. Return type above not implemented, but you can put it to a boolean or status flag, whatever.
In both approaches, the parameter to the Save() function is not of type T. In the first one, it is ISaveableModel<T>, and in the second, it is BaseModel<T>. Since the repository is a generic based on T, Save method will expect a variable of type T. You can add a simple cast to T before you call Save to fix it.
Alternatively, your IRepostory<T> can be changed to
public interface IRepository<T>
{
T Save(ISaveableModel<T> model);
}
which makes more sense.

Categories

Resources