I know this question has probably been asked many times and my title probably needs some help so feel free to close this question after pointing me to a duplicate... just not sure how to properly search for the answer at the moment.
I've got a situation where a variable may need to hold and instance of ISolrOperations<Class1>
or it may need to hold an instance of ISolrOperations<Class2>
. The problem is that there is no base version of the interface and so there's no class I can define the variable as (other than object, which obviously has no knowledge of ISolrOperations<T>
's methods) to be able to hold either class.
So the only solutions I know of are either a) Do an if/else statement where I do everything I need with ISolrOperations<Class1>
in one block and everything I need in ISolrOperations<Class2>
in the other block even though each block will basically contain duplicate code. Or b) I could make the variable dynamic and just lose some compile time validation of my code.
I'm trying to think if there is some way I can create a generic wrapper class that has a non-generic base. And maybe the base has to treat it as an object but uses reflection... but them I'm like screw it; if I have to go through that trouble may as well just use the dynamic keyword.
Is there a more "proper" design pattern to handle this scenario? Or is my choice basically between dynamic or writing a lot of code just to make myself feel like I'm doing it "right" when dynamic is really the most practical solution?
Edit: Actually I'm not sure if dynamic would solve this problem :/
Edit 2: Nope... other code uses lambdas with the variable which requires casting it which I obviously don't know what to cast to at compile time so that won't work.
Although I am not sure, this approach might help. This approach uses adapter pattern .
public interface ISolrOperations<T>
{
SqlQuery<T> Execute();
}
public interface ISolrOperationsAdapter
{
IEnumerable<Base> Execute();
}
//Idealy you have interfaces
public class Base { }
public class Class1 : Base { }
public class Class2 : Base { }
public abstract class SolrOperationsAdapter : ISolrOperationsAdapter
{
protected SolrOperationsAdapter()
{
}
public IEnumerable<Base> Execute()
{
return ExecuteImpl();
}
protected abstract IEnumerable<Base> ExecuteImpl();
}
public class GenericSolrOperationsAdapter<T> : SolrOperationsAdapter
{
private readonly ISolrOperations<T> _solrOperations;
public static ISolrOperationsAdapter From(ISolrOperations<T> solrOperations)
{
return new GenericSolrOperationsAdapter<T>(solrOperations);
}
protected GenericSolrOperationsAdapter(ISolrOperations<T> solrOperations)
: base()
{
_solrOperations = solrOperations;
}
//If you define interfaces you can return return IEnumerable<IInterface>
protected override IEnumerable<Base> ExecuteImpl()
{
//here you can somehow convert result of query to your types(Class1, Class2 or some interface behind)
return _solrOperations.Execute().ConvertTo<IEnumerable<Base>>();
}
}
Usage example:
ISolrOperations<Class1> solrOperations = new SolrOperationsImplementation()
ISolrOperationsAdapter adapter = GenericSolrOperationsAdapter<Class1>.From(solrOperations);
IEnumerable<Base> result = adapter.Execute();
Wrap the class in a generic adapter class that implements the required interface.
This is called the adapter pattern in case you want to search for examples of it.
Example of a generic adapter:
public class SomeGenericInterfaceAdapter<T> : INonGenericInterface
{
private IGenericInterface<T> _someGenericInterface;
public SomeGenericInterfaceAdapter(IGenericInterface<T> someGenericInterface)
{
_someGenericInterface = someGenericInterface;
}
public void SomeMethod()
{
_someGenericInterface.SomeMethod();
}
}
public interface INonGenericInterface
{
void SomeMethod();
}
public interface IGenericInterface<T>
{
void SomeMethod();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.