Unity registrations override each other - c#

I'm using Unity in with C#. I have an interface I call IConnectionStringLoader, which have two derived interfaces.
public interface IConnectionStringLoader
{
string Get();
void Write();
}
public interface IDbConnectionStringLoader : IConnectionStringLoader
{
}
public interface IMetaDataConnectionStringLoader : IConnectionStringLoader
{
}
It has only one implementation:
public class ConnectionStringLoader : IDbConnectionStringLoader, IMetaDataConnectionStringLoader
{
private readonly string _connectionStringName;
public ConnectionStringLoader(string connectionStringName)
{
_connectionStringName = connectionStringName;
}
public string Get()
{
var cs = ConfigurationManager.ConnectionStrings[_connectionStringName];
if (cs != null)
{
return cs.ConnectionString;
}
return null;
}
public void Write()
{
Console.WriteLine(_connectionStringName);
}
}
My registration looks like this:
container.RegisterType<IMetaDataConnectionStringLoader, ConnectionStringLoader>(new InjectionConstructor("MetaConnection"));
container.RegisterType<IDbConnectionStringLoader, ConnectionStringLoader>(new InjectionConstructor("DbConnection"));
The point of the interfaces is that I can inject the different interfaces in my classes and get the correct connectionstring for each implementation. But the problem is that whatever registration is done last will overwrite the previous one.
var foo = _container.Resolve<IDbConnectionStringLoader>();
var bar = _container.Resolve<IMetaDataConnectionStringLoader>();
foo.Write();
bar.Write();
Output is:
DbConnection
DbConnection
If I invert the order of the registration the output will be MetaConnection twice. So my conclusion so far is that the last registration overwrites the previous one. However, if I change the implementation to a derived class it works:
public class SomeOtherConnectionStringLoader : ConnectionStringLoader
{
public ConnectionStringLoaderImpl(string connectionStringName) : base(connectionStringName)
{
}
}
And change the registrations:
container.RegisterType<IMetaDataConnectionStringLoader, ConnectionStringLoader>(new InjectionConstructor("MetaConnection"));
container.RegisterType<IDbConnectionStringLoader, SomeOtherConnectionStringLoader >(new InjectionConstructor("DbConnection"));
Now everything works, but I don't understand why. I've tried different lifetimemanagers, but with the same result. I thought Unity would try to create an instance of ConnectionStringLoader with the "correct" injectionparameter based on the interface, but there's seems to be some other logic at play here.
Any suggestions why the registrations overwrite each other?

Honestly speaking, the way you are using the interfaces looks strange to me because there are two interfaces implemented only by the same class. I would find more natural to follow the next approach using registration names:
// If it is a loader the Write method makes no sense (IConnectionStringRepository?)
public interface IConnectionStringLoader
{
string Get();
void Write();
}
public class ConnectionStringLoader : IConnectionStringLoader
{
private readonly string _connectionStringName;
public ConnectionStringLoader(string connectionStringName)
{
_connectionStringName = connectionStringName;
}
public string Get()
{
var cs = ConfigurationManager.ConnectionStrings[_connectionStringName];
if (cs != null)
{
return cs.ConnectionString;
}
return null;
}
public void Write()
{
Console.WriteLine(_connectionStringName);
}
}
Registrations:
container.RegisterType<IConnectionStringLoader, ConnectionStringLoader>("Database", new InjectionConstructor("MetaConnection"));
container.RegisterType<IConnectionStringLoader, ConnectionStringLoader>("Metadata", new InjectionConstructor("DbConnection"));
Resolutions:
var foo = _container.Resolve<IConnectionStringLoader>("Database");
var bar = _container.Resolve<IConnectionStringLoader>("Metadata");
foo.Write();
bar.Write();

I'm not familiar with Unity. But it seems they are mapping to same instance. So you should change lifetime of ConnectionStringLoader (Per dependency).
If you will not share instance, why do you put all things in one class ? ConnectionStringLoader Methods = IDbConnectionStringLoader methods + IMetaDataConnectionStringLoader methods.
When you resolve IDbConnectionStringLoader it will not use IMetaDataConnectionStringLoader methods which is already in instance (vice versa it's true).
Crating two different derived class is better at this point:
Abstract class:
public abstract class ConnectionStringLoader : IConnectionStringLoader
{
private readonly string _connectionStringName;
public ConnectionStringLoader(string connectionStringName)
{
_connectionStringName = connectionStringName;
}
public string Get()
{
var cs = ConfigurationManager.ConnectionStrings[_connectionStringName];
if (cs != null)
{
return cs.ConnectionString;
}
return null;
}
public void Write()
{
Console.WriteLine(_connectionStringName);
}
}
Derived Classes:
public sealed class DbConnectionStringLoader : ConnectionStringLoader, IDbConnectionStringLoader
{
public DbConnectionStringLoader(string connectionStringName):base(connectionStringName)
{
}
//Implement methods here just belongs to IDbConnectionStringLoader
}
public sealed class MetaDataConnectionStringLoader : ConnectionStringLoader, IMetaDataConnectionStringLoader
{
public MetaDataConnectionStringLoader(string connectionStringName):base(connectionStringName)
{
}
//Implement methods here just belongs to IMetaDataConnectionStringLoader
}

Surprisingly it does call ConnectionStringLoader ctor twice, but with same injection member. If you look at container.Registrations, there are indeed two registrations so it is not override one with other. I did look at implementation of RegisterType, but didn't get my head around it.
One alternative is to name your registrations, not sure if it fits into your overall unity bootstrap strategy.
container.RegisterType<IMetaDataConnectionStringLoader, ConnectionStringLoader>("bar", new InjectionConstructor("MetaConnection"));
container.RegisterType<IDbConnectionStringLoader, ConnectionStringLoader>("foo", new InjectionConstructor("DbConnection"));
var foo = container.Resolve<IDbConnectionStringLoader>("foo");
var bar = container.Resolve<IMetaDataConnectionStringLoader>("bar");

Related

How to avoid casting to a specific interface

Background info
I have a set of interfaces/classes as follows. For the sake of simplicity imagine more properties, collections etc.
interface IMaster
{
//Some properties
}
interface IB : IMaster
{
string PropOnA { get; set }
}
interface IC : IMaster
{
string PropOnB { get; set }
}
class B : IB
class C : IC
...
These contracts were designed to store data(which is held in a slightly different format in each case). There is a lot of code that uses these contracts to get the data, format it, process it, write etc.
We have developed an entire library that does not see the concrete implementations(B,C) of any of these contracts by inverting control and allow the user to use our 'default implementations' for each contract or just loading in their own. We have registry where the user can register a different implementation.
To this end I have implemented a kind of strategy pattern where there exists a strategy for each contract type based on the task at hand. For the sake of simplicity lets say the task is writing, in reality it is much more complicated.
interface IWriteStrategy
{
public Write(IMaster thing);
}
class WriterA : IWriteStrategy
class WriterB : IWriteStrategy
etc
The above concrete strategies are also never 'seen' in our library, the client must register their own implementation or our default version.
Design flaw??
I am not liking the cast in every strategy that is now necessary.
public classWriterA : IWriteStrategy
{
public void Write(IMaster thing)
{
if(thing is IA thingA)
//do some work
}
}
public classWriterB : IWriteStrategy
{
public void Write(IMaster thing)
{
if(thing is IB thingB)
//do some work
}
}
What we want to do is be able to loop through a list of IMaster objects and run some operations.
foreach(var thing in Things)
{
var strategy = GetStrategy(thing.GetType()); //this gets the strategy object from our `registry` if one exists
strategy.Execute(thing);
}
The above design allows this but there seems to be a flaw which I cant for the life of me spot a solution to. We have to cast to the specific interface within each strategy implementation.
I have tried with generics, but just cant seem to nail it.
Question
What would be a better way of designing this to avoid the cast but still be able to loop through a list of IMaster things and treat them the same? Or is the cast absolutely necessary here?
I am trying to follow a SOLID design but feel the cast is messing with this as the client implementing the strategies will have to do the cast in order to get anything to work within the Write method.
[Edit]
I have updated the classes implementing the IWriteStrategy.
If you rarely add new IMaster specializations, but often add new operations OR need to make sure operation providers (e.g writer) needs to support ALL specializations then the Visitor Pattern is a perfect fit.
Otherwise you basically need some kind of service locator & registration protocol to map operation providers/strategies to IMaster specializations.
One way you could do it is define generic interfaces such as IMasterWriter<T> where T:IMaster which can then be implemented like IBWriter : IMasterWriter<IB> which defines the mapping.
From that point you only need a mechanism that uses reflection to find a specific IMasterWriter implementor for a given type of IMaster and decide what to do if it's missing. You could scan assemblies early to detect missing implementations at boot rather than failing later too.
Maybe it is appropriate to use Strategy pattern and just give an implementation and execute it. Let me show an example.
interface IMaster
{
void ExecuteMaster();
}
class MasterOne : IMaster
{
public void ExecuteMaster()
{
Console.WriteLine("Master One");
}
}
class MasterTwo : IMaster
{
public void ExecuteMaster()
{
Console.WriteLine("Master Two");
}
}
and
interface IWriteStrategy
{
void Write(IMaster thing);
}
class WriterA : IWriteStrategy
{
public void Write(IMaster thing)
{
Console.WriteLine("Writer A");
thing.ExecuteMaster();
}
}
class WriterB : IWriteStrategy
{
public void Write(IMaster thing)
{
Console.WriteLine("Writer B");
thing.ExecuteMaster();
}
}
and code to execute:
static void Main(string[] args)
{
List<IWriteStrategy> writeStrategies = new List<IWriteStrategy>()
{
new WriterA(),
new WriterB()
};
List<IMaster> executes = new List<IMaster>()
{
new MasterOne(),
new MasterTwo()
};
for (int i = 0; i < writeStrategies.Count(); i++)
{
writeStrategies[i].Write(executes[i]);
}
}
what about this, you will have all your casts in one strategy factory method:
public interface IWriterStrategy
{
void Execute();
}
public class WriterA : IWriterStrategy
{
private readonly IA _thing;
public WriterA(IA thing)
{
_thing = thing;
}
public void Execute()
{
Console.WriteLine(_thing.PropOnA);
}
}
public class WriterB : IWriterStrategy
{
private readonly IB _thing;
public WriterB(IB thing)
{
_thing = thing;
}
public void Execute()
{
Console.WriteLine(_thing.PropOnB);
}
}
public static class WriterFactory
{
public static List<(Type Master, Type Writer)> RegisteredWriters = new List<(Type Master, Type Writer)>
{
(typeof(IA), typeof(WriterA)),
(typeof(IB), typeof(WriterB))
};
public static IWriterStrategy GetStrategy(IMaster thing)
{
(Type Master, Type Writer) writerTypeItem = RegisteredWriters.Find(x => x.Master.IsAssignableFrom(thing.GetType()));
if (writerTypeItem.Master != null)
{
return (IWriterStrategy)Activator.CreateInstance(writerTypeItem.Writer, thing);
}
throw new Exception("Strategy not found!");
}
}
public interface IMaster
{
//Some properties
}
public interface IA : IMaster
{
string PropOnA { get; set; }
}
public interface IB : IMaster
{
string PropOnB { get; set; }
}
public interface IC : IMaster
{
string PropOnC { get; set; }
}
public class ThingB : IB
{
public string PropOnB { get => "IB"; set => throw new NotImplementedException(); }
}
public class ThingA : IA
{
public string PropOnA { get => "IA"; set => throw new NotImplementedException(); }
}
public class ThingC : IC
{
public string PropOnC { get => "IC"; set => throw new NotImplementedException(); }
}
internal static class Program
{
private static void Main(string[] args)
{
var things = new List<IMaster> {
new ThingA(),
new ThingB()//,
//new ThingC()
};
foreach (var thing in things)
{
var strategy = WriterFactory.GetStrategy(thing); //this gets the strategy object from our `registry` if one exists
strategy.Execute();
}
}
}

Ninject Binding Generic Interfaces

I'm trying to use DI to bind a different implementation of my networking class. I've been able to do this successfully using a none generic version of the class. My implementation is as follows:
class MainClass
{
public static void Main(string[] args)
{
IKernel kernel;
// Hardcode here but will be managed by build system.
bool runningInProd = false;
if (runningInProd)
{
kernel = new StandardKernel(new RealNetworkModule());
}
else
{
kernel = new StandardKernel(new FakeNetworkModule());
}
Session session = kernel.Get<Session>();
session.Authenticate();
}
public class RealNetworkModule : NinjectModule
{
public override void Load()
{
Bind(typeof(IRequestSender)).To(typeof(RealRequestSender));
}
}
public class FakeNetworkModule : NinjectModule
{
public override void Load()
{
Bind(typeof(IRequestSender)).To(typeof(FakeRequestSender));
}
}
}
Class that uses my IRequestSender:
public class Session
{
IRequestSender requestSender;
[Inject]
public Session(IRequestSender requestSender)
{
this.requestSender = requestSender;
}
public void Authenticate()
{
Console.WriteLine(requestSender.Send("Hello There"));
}
}
The IRequestSender interface:
public interface IRequestSender
{
string Send(string request);
}
And the two different implementations:
public class RealRequestSender: IRequestSender
{
public string Send(string request)
{
return "RealRequestSender right back at you: " + request;
}
}
public class FakeRequestSender: IRequestSender
{
public string Send(string request)
{
return "FakeRequestSender right back at you: " + request;
}
}
This is very straightforward and it works; however, what I need is for my IRequestSender to use Generic types rather than string for input output:
public interface IRequestSender<RequestT, ResponseT> where RequestT: class where ResponseT: class
{
RequestT Send(RequestT request);
}
And the impl's:
public class FakeRequestSender<RequestT, ResponseT> : IRequestSender<RequestT, ResponseT> where RequestT : class where ResponseT : class
{
public RequestT Send(RequestT request)
{
throw new NotImplementedException();
}
}
public class RealRequestSender<RequestT, ResponseT> : IRequestSender<RequestT, ResponseT> where RequestT : class where ResponseT : class
{
public RequestT Send(RequestT request)
{
throw new NotImplementedException();
}
}
I've come across several examples that address this issue and I've tried to base my implementation on them but I have failed. Here are the two problems that I'm running into:
1) Binding: this is the main problem. Here is what my binding looks like based on solutions I have seen online:
public class RealNetworkModule : NinjectModule
{
public override void Load()
{
Bind(typeof(IRequestSender<>)).To(typeof(RealRequestSender<>));
}
}
VSCode gives me the error:
Program.cs(29,29): Error CS0305: Using the generic type 'IRequestSender<RequestT, ResponseT>' requires 2 type arguments (CS0305) (DI)
Based on this error and what I have read online it is still not clear to me what I need to do here.
2) Accessing IRequestSender: the solution to this might be clear once I know how to fix binding. In the original implementation I used [Inject] to get access to the IRequestSender I need in my Sessions class. However now in the generic version I imagine I will not be able to do this. If I were to use RequestSender without DI it would look like:
RequestSender <AuthRequest, AuthResponse> requestSender = new RequestSender<AuthRequest, AuthResponse>();
or
RequestSender <UserRequest, UserResponse> requestSender = new RequestSender< UserRequest, UserResponse >();
for any number of different types.
So I'm not sure how to go about accessing the RequestSender in this scenario.
Given your current interface, you'll have to specify the generic type arguments when injecting. Assuming your request and response are both strings, your constructor would look like:
public Session(IRequestSender<string, string> requestSender)
{
this.requestSender = requestSender;
}
If you don't want to specify the arguments at creation/injection time, you'll have to change the design a bit. I can't say for certain with the sample code you provided, but it might be possible to remove the generic type args from your interface and place them on the method instead:
public interface IRequestSender
{
RequestT Send<RequestT, ResponseT>(RequestT request)
where RequestT: class
where ResponseT: class;
}
With that definition, you'd inject IRequestSender, and then specify the generic type parameters when calling. For example,
string myResponse = requestSender.Send<string, string>("my string");

Using inherited members from base class (moving repeatable code into base class)

I often use
using (var context = new SomeDataContext(SomeDataContext.ConnectionString))
{
...
}
where
abstract class DataContextBase: DataContext { ... }
partial class SomeDataContext: DataContextBase
{
public const string DatabaseFile = "blablabla.mdf";
public static readonly string ConnectionString = string.Format(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename={0};Integrated Security=True", DatabaseFile);
}
Question: Is it possible to hide creation of SomeDataContext instance and ConnectionString deep into DataContextBase?
I want to define only file name in inherited classes
partial class SomeDataContext: DataContextBase
{
public const string DatabaseFile = "blablabla.mdf";
}
and to be able to create instances like this
var context = SomeDataContext.PropertyInBaseClassWhichCreatesInstanceOfInheritedClass;
P.S.: I add at first of how I tried to overcome the problem (without success tbh), but then I deleted it (I was making this post over hour!), because it makes question too noisy. It may looks easy at first, until you (or is it only me?) try to solve it. I tagged it dbml because of specific to DataContext things: you can't use singleton, etc.
Unfortunately, there isn't some sort of virtual static, and if you call SomeDataContext.StaticPropertyInBaseClass, it compiles to the same as DataContextBase.StaticPropertyInBaseClass. I think the best you can do is something like this:
// upside: simple SomeDataContext.Instance for external users
// downside: more code in SomeDataContext
partial class SomeDataContext : DataContextBase
{
private const string DatabaseFile = "blablabla.mdf";
public static SomeDataContext Instance
{
get
{
return new SomeDataContext(GetConnectionString(DatabaseFile));
}
}
}
abstract class DataContextBase
{
protected static string GetConnectionString(string databaseFile)
{
return string.Format(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename={0};Integrated Security=True", databaseFile);
}
}
// e.g. using (var context = SomeDataContext.Instance)
Or
// upside: just one line in child class
// downside: a little harder for external callers, with a little less type safety
// downside: as written, requires child class to have parameterless constructor
partial class SomeDataContext : DataContextBase
{
protected override string DatabaseFileInternal { get { return "blablabla.mdf"; } }
}
abstract class DataContextBase
{
protected abstract string DatabaseFileInternal { get; }
private string ConnectionString
{
get
{
return string.Format(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename={0};Integrated Security=True", DatabaseFileInternal);
}
}
public static T GetInstance<T>() where T : DataContextBase, new()
{
using (var tInst = new T())
return (T)Activator.CreateInstance(typeof(T), tInst.ConnectionString);
}
}
// e.g. using (var context = DataContextBase.GetInstance<SomeDataContext>())

Dependency Strategy when using different dependency depending on parameters

Having this interface :
public interface FileManager {
string UploadFile(HttpPostedFileBase file);
string UploadFile(Uri uri);
}
my implementation will looks like :
public class FileManagerAzure : FileManager {
private FileParser parser;
FileManagerAzure(FileParser parser){
this.parser = parser; // Can this be a constructor injection??
}
public string UploadFile(HttpPostedFileBase file) {
return parser.Parse(file); // Should I Inject the parser here depending on type ??
}
public string UploadFile(Uri uri) {
return parser.Parse(uri);
}
}
this have a dependency on FileParser which looks like following :
public interface FileParser {
string Parse(object source)
}
and ideally I would like to have some parsers implementations (this doesn't work of course) :
public class FileParserHttpPostedFileBase : FileParser {
string Parse(HttpPostedFileBase source) {
return file.FileName;
}
}
public class FileParserUri : FileParser {
string Parse(Uri source) {
return Uri.ToString();
}
}
Is there anyway to create the concrete parser dependency depending on the parameter passed to UploadFile() ? this have to be a setter injection ? Is this good, or are any other strategy I can follow ?
I have to make my FileParser interface receive an object as source. This doesn't sound like it should since I have a limited set allowed input types, certainly not object. In this case HttpPostedFileBase and Uri. How can I limit the scope for this ?
You can inject the dependencies via the constructor. That's the way I'd choose whenever possible. That means you can't use an IoC container for instantiation, though. You can use an abstract factory pattern to encapsulate the decision making of what concrete parser to inject, and have an IoC container inject the concrete factory into the calling class(es).
Seems like overkill, though. Since your FileManager interface exposes methods for both argument types why not inject both parser types? I'd make the FileParser type generic for that, so you don't need a new interface for every new parser.
public interface FileParser<T>
{
string Parse(T value);
}
public class UriParser : FileParser<Uri>
{
string Parse(Uri value)
{
// implementation
}
}
You could implement the FileManagerAzure like this then:
public class FileManagerAzure : FileManager {
private FileParser<Uri> uriParser;
private FileParser<HttpPostedFileBase> postedFileParser;
FileManagerAzure(FileParser<Uri> uriParser, FileParser<HttpPostedFileBase> postedFileParser){
this.uriParser = uriParser;
this.postedFileParser = postedFileParser;
}
public string UploadFile(HttpPostedFileBase file) {
return this.postedFileParser.Parse(file);
}
public string UploadFile(Uri uri) {
return this.uriParser.Parse(uri);
}
}
This implementation can be instantiated by an IoC container no problem too.
I think you should use generic typing:
public interface FileParser<T> {
string Parse(T source)
}
This way you can easily have multiple implementations as follows:
public class FileParserHttpPostedFileBase : FileParser<HttpPostedFileBase> {
public string Parse(HttpPostedFileBase source) {
return file.FileName;
}
}
public class FileParserUri : FileParser<Uri> {
public string Parse(Uri source) {
return Uri.ToString();
}
}
And this way you remove the ambiguity in your design because now it becomes clear what to inject into the constructor:
public class FileManagerAzure : FileManager {
private FileParser<HttpPostedFileBase> httpParser;
private FileParser<Uri> uriParser;
FileManagerAzure(FileParser<HttpPostedFileBase> httpParser,
FileParser<Uri> uriParser){
this.httpParser = httpParser;
this.uriParser = uriParser;
}
public string UploadFile(HttpPostedFileBase file) {
return httpParser.Parse(file);
}
public string UploadFile(Uri uri) {
return uriParser.Parse(uri);
}
}
However, if the FileManagerAzure only delegates to its dependencies like this, you should question whether the FileManager abstraction has any use. A consumer of the FileManager could depend directly on one of the FileParser<T> abstractions. And if the FileParser<T> only has that one line of code, we could even argue that you might even want to do without that abstraction (however, as always: your mileage may vary).

Func delegate to declared method

Having these two methods declared in a non-generic class, which share the same signature:
private TypeResolverResult<T> TryRetrieveFromReusable<T>(TypeResolverConfiguration<T> typeResolverConfiguration) where T : class
{
return null;
}
private TypeResolverResult<T> BuildNew<T>(TypeResolverConfiguration<T> typeResolverConfiguration) where T : class
{
return null;
}
How can I create a delegate that represents these methods' signature?
I can't seem to get it, I tried:
private Func<TypeResolverConfiguration<T>, TypeResolverResult<T>> _typeResolveFunc;
But obvious this does not work because the class is non-generic and I can't change that.
Thanks
UPDATE
This is more or less what I need:
public class Manager : ATypeResolver, IManager
{
private neeedDelegate;
public Manager(RuntimeConfiguration runtimeConfiguration, IList<RepositoryContainer> repositories)
{
if (runtimeConfiguration.WhatEver)
{
neeedDelegate = TryRetrieveFromReusable;
}
else
{
neeedDelegate = BuildNew;
}
}
public override TypeResolverResult<T> Resolve<T>() where T : class
{
//Want to avoid doing this:
if (runtimeConfiguration.WhatEver)
{
TryRetrieveFromReusable(new TypeResolverConfiguration<T>());
}
else
{
BuildNew(new TypeResolverConfiguration<T>());
}
//and have just this
neeedDelegate<T>(new TypeResolverConfiguration<T>());
}
private TypeResolverResult<T> TryRetrieveFromReusable<T>(TypeResolverConfiguration<T> typeResolverConfiguration) where T : class
{
return null;
}
private TypeResolverResult<T> BuildNew<T>(TypeResolverConfiguration<T> typeResolverConfiguration) where T : class
{
return null;
}
}
Update From what I can see, an approach like this should work, as long as ATypeResolver has a where T : class on Resolve<T>:
public class Manager : ATypeResolver, IManager
{
private bool tryRetrieveFromReusable;
public Manager(RuntimeConfiguration runtimeConfiguration, IList<RepositoryContainer> repositories)
{
this.tryRetrieveFromReusable = runtimeConfiguration.WhatEver;
}
public override TypeResolverResult<T> Resolve<T>()
{
var typeResolver = tryRetrieveFromReusable ? (TypeResolver<T>)TryRetrieveFromReusable : BuildNew;
return typeResolver(new TypeResolverConfiguration<T>());
}
}
This uses a custom delegate type (a Func like you have should work too):
public delegate TypeResolverResult<T> TypeResolver<T>(
TypeResolverConfiguration<T> typeResolverConfiguration) where T : class;
If you like, you can move the var typeResolver = ... line to its own method, to separate the logic and allow you to use it from more than just Resolve. If you did that, Resolve might be as simple as: return GetTypeResolver<T>()(new TypeResolverConfiguration<T>());.
You seem to not understand exactly how generics work. I'll give a quick overview, but read the MSDN.
When you have a generic class
public class Foo<T>
{
public T Bar {get; set;}
}
And you use it something like this
Foo<int> intFoo = new Foo<int>();
Foo<string> stringFoo = new Foo<string();
At compile time, the compiler will detect the two usages of the generic type. It will create a type of each usage. So your assembly will have types that look something like this (no not exactly, but let's play pretend so that we humans can understand).
public class FooInt
{
public int Bar { get; set; }
}
public class FooString
{
public string Bar { get; set; }
}
And it will replace all uses of Foo<int> with FooInt and Foo<string> with FooString
Now if we have a non-generic class with a generic method
public class Foo
{
public T GetBar<T>() { ..... }
}
And you use it like this
Foo foo = new Foo();
int x = foo.GetBar<int>();
string s = foo.GetBar<string();
The compiler will generate
public class Foo
{
public int GetBarInt() { ..... }
public string GetBarString() { ..... }
}
And it will replace GetBar<T> with GetBarInt and GetBar<string> with GetBarString
But fields aren't like that. If you have a class that looks like so
public class Foo
{
public T Bar;
}
You cannot do this
Foo foo = new Foo();
foo.Bar<int> = 1;
foo.Bar<string> = "test";
The compiler just doesn't understand that. I'm not an expert on the internals, but my guess is that because this points to a place in memory, the compile cannot generate the generic usages at compile time.
But the point I am trying to make is this. Generics are not some magical "I don't need to specify the type" feature. They are hints to the compile that say "I am going to do this same thing multiple times, I want you to generate the code for me."

Categories