Lots of questions with these keywords; I sifted through the first 30 or so then gave up.
I have interfaces like so:
public interface IColumnRule
{
int Length { get; set; }
string Name { get; set; }
object Parse(string toParse);
int Position { get; set; }
Type Type { get; }
}
public interface IColumnRule<T> : IColumnRule
{
ColumnRule<T>.RuleFluentInterface<T> Configure { get; }
new T Parse(string rowdata);
Func<string, T> ParsingFunction { get; set; }
}
... the idea being, one would implement the IColumnRule<T> to create a strongly-typed column parser utilizing the Func<string, T>.
The problem is, I store these IColumnRule<T> concretes in an IList<IColumnRule> container. There are multiple types of IColumnRule<T>, each implementing on a different type. When I invoke the Parse method on the IColumnRule interface, I am expecting the new Parse(string) method of the subclass to be called, but the base Parse is the one actually being called.
How can I invoke the subclass generic T Parse(string) method from a collection of IColumnRule using the interface's object Parse(string) ... or is this impossible?
Your implementation of IColumnRule<T> would have to provide a compliant Parse method. Given your code, the easiest way to do that is with an protected abstract method in your base class which is overridden in your subclass.
public abstract class ColumnRule : IColumnRule
{
...
public object Parse(string rowdata)
{
return this.ParseInternal(rowdata);
}
protected abstract object ParseInternal(rowdata);
}
public class ColumnRule<T> : ColumnRule, IColumnRule<T>
{
...
public new T Parse(string rowdata)
{
// strong-typed parse method
}
protected override object ParseInternal(string rowdata)
{
return this.Parse(rowdata); // invokes strong-typed method
}
}
When I invoke the Parse method on the IColumnRule interface, I am expecting the new Parse(string) method of the subclass to be called, but the base Parse is the one actually being called.
Yes, it would. You've got two methods which are unrelated as far as the type system, CLR and compiler are concerned.
How can I invoke the subclass generic T Parse(string) method from a collection of IColumnRule using the interface's object Parse(string) ... or is this impossible?
The simplest approach would be to have an abstract class implementing this as:
public abstract ColumnRuleBase<T> : IColumnRule<T>
{
public object Parse(string toParse)
{
IColumnRule<T> genericThis = this;
return genericThis.Parse(toParse);
}
...
}
(If you had the two method names being different, it would be slightly simpler.)
You'd have to know the type somehow:
List<IColumnRule> rules; // populated from somewhere
foreach (IColumRule<int> rule in rules.OfType<IColumnRule<int>>()) {
int foo = rule.Parse(rowData);
}
Or just cast a known element:
int foo = ((IColumnRule<int>)rules[5]).Parse(rowData);
Related
I want to override BuildFilter Method in the derived class. I have a virual BuildFilter Method with the following signatures
public abstract class BaseSearchProperty <TEntity> : ISearchResultProperty<TEntity>
{
public virtual List<AppliedFilter> BuildFilter(object value)
{
return new List<AppliedFilter>();
}
}
i know the BuildFilter method override types one is string and another one is a List of String List<string>. i have written the override methods in the derived class as below
public class IndustrySearchProperty : BaseSearchProperty<API.ISearchResult>
{
public override List<AppliedFilter> BuildFilter(string filterValue,)
{
var appliedFilters = new List<AppliedFilter>();
return appliedFilters;
}
public override List<AppliedFilter> BuildFilter(List<string> filterValue)
{
var appliedFilters = new List<AppliedFilter>();
return appliedFilters;
}
}
but am getting error like no suitable method found to override. I know what this error is both parent class signature and child class signature needs to be same. Is there any other way that i solve this problem??
both parent class signature and child class signature needs to be same
Yes. There is no clean way.
Two things you can do:
Get the object in the overrided method and cast to whatever type needed or
Add a new type parameter
like this:
public abstract class BaseSearchProperty <TEntity,TFilter> : ISearchResultProperty<TEntity>
{
public virtual List<AppliedFilter> BuildFilter(TFilter value)
{
return new List<AppliedFilter>();
}
}
I recommend neither. This is a code smell in my mind showing you are not using inheritance correctly. And it probably doesn't support Liskov and other principles.
In my abstract base class AbstractType, I have an abstract auto-implemented property Value of unknown type. All my derived classes implement this property with their own types, such string or double. Normally, I know you would just make it AbstractType<T> and have the property be T Value { ... }. However, I don't have the ability to use generics in this case. In AbstractType, I'm trying to implement a method that returns a new derived class from AbstractType, so if I use generics, the caller has to know the type. If I make Value type object, then the caller has to wrap the object to the correct type - very inconvenient type/instance checking.
Here's what my class structure looks like (the method is simplified for the sake of demonstration):
abstract class AbstractType
{
public abstract ??? Value { get; set; }
AbstractType FromValue(int i)
{
if (i == 0)
return new NumberType();
else
return new StringType();
}
}
class NumberType : AbstractType
{
public override double Value { get; set; }
}
class StringType : AbstractType
{
public override string Value { get; set; }
}
Is there any way to do this without using generics?
I want to create class system to generalize getting and posting data from some data source. I have two methods: GetData and PostData. Both methods should have some kind of input, and GetData should also have return type. I tried to write generic interface and to implement it in "DatabaseSource" class:
public class QueryParameter
{
public QueryParameter()
{
this.Direction = ParameterDirection.Input;
}
public string Name { get; set; }
public object Value { get; set; }
public ParameterDirection Direction { get; set; }
}
public class InputBase
{
public InputBase()
{
ResultMapping = new Dictionary<string, string>();
Parameters = new List<QueryParameter>();
}
public Dictionary<string, string> ResultMapping { get; set; }
public List<QueryParameter> Parameters { get; set; }
}
public class DatabaseInput: InputBase
{
public string Query { get; set; }
public DatabaseCommandType CommandType { get; set; }
}
public interface IDataSource<I> where I: InputBase
{
IEnumerable<T> GetData<T>(I input);
void PostData(I Input);
}
Now i tried to implement interface like this:
public class DatabaseDataSource: IDataSource<DatabaseInput>
{
public IEnumerable<T> GetData<T>(DatabaseInput Input)
{
//implementation
}
public void PostData(DatabaseInput Input)
{
//implementation
}
}
But i have a problem when I try to instantiate data source like this:
IDataSource<InputBase> dataSource = new DatabaseDataSource();
I cannot use DatabaseInput because this code is in some kind of factory method and I should be able to instantiate other IDataSource implementations.
In short I want to have Input and Output as generic types, and to constraint Input to match concrete IDataSource implementation.
If I'm understanding this correctly (and it's admittedly not 100% clear to me), your data source needs to define both the input and the output. If you do this:
public IEnumerable<T> GetData<T>(DatabaseInput Input)
Then the actual implementation of that method might vary significantly according to what T is. You don't want a scenario of that method where you're inspecting the type of T and branching your code accordingly.
Perhaps what you want is something like this:
public interface IDataSource<TInput, TOutput> where TInput: InputBase
{
IEnumerable<TOutput> GetData(TOutput input);
void PostData(TInput Input);
}
But even then you've got an interface that's defining two seemingly unrelated operations. (It seems unlikely that TInput can be used both as a query to retrieve data and as a command to post/modify data.)
So perhaps you could break it down further:
public interface IDataSource<TInput, TOutput> where TInput: InputBase
{
IEnumerable<TOutput> GetData(TOutput input);
}
public interface IDataCommand<TInput> where TInput:InputBase
{
void PostData(TInput Input);
}
To instantiate it you could use an abstract factory:
public interface IDataSourceFactory<TInput, TOutput>
{
IDataSource<TInput, TOutput> Create();
void Release(IDataSource<TInput, TOutput> created);
}
The reason for that is because it avoids the need for your class to call var dataSource = new [whatever]. If you do that then it somewhat defeats the purpose of implementing an interface. Regardless of what interface you implement, as soon as you explicitly call new and create a specific type, your class is coupled to that type, not the interface.
That moves the original problem. What is the implementation of the abstract factory? The good news is that the class that depends on the factory doesn't care what the implementation of the factory is. But you'll still need one. One way to go about it is using a DI container. Windsor is helpful because it provides a pattern for creating abstract factories. This blog post describes how to do that in more detail.
Check out Covariance and Contravariance. https://msdn.microsoft.com/en-us/library/mt654055.aspx
You can use the where constraint, click here for more information about constraints.
where T : class //The type argument must be a reference type; this applies also to any class, interface, delegate, or array type.
where T : <interface name> //The type argument must be or implement the specified interface. Multiple interface constraints can be specified. The constraining interface can also be generic.
public abstract class A
{
// constructors omitted
public abstract A Create(SomeData data);
}
public class B : A
{
// constructors omitted
public override A Create(SomeData data)
{
return new B(data);
}
}
What I want is to be able to make the Create method static, so that I can get an instance of B without having to create a useless instance with an empty constructor. (If you're wondering why, A is actually a generic type of the form A<TFoo, TBar>, where TBar corresponds to the derived types. As we all know, you can't instantiate a generic type using a constructor that takes any arguments.)
I am already aware that static methods are decoupled from the object hierarchy, only relying on the name of the type. That means I can't have Create as an abstract method that I force all descendants to implement. Is there another way I can implement this pattern?
Something like this might work, depends on your requirements
public abstract class A
{
public string Data { get; set; }
public static T Create<T>(string data) where T : A, new()
{
return new T() { Data = data };
}
}
public class B : A { }
then can do
A foo = A.Create<B>("foo");
There is simply no way to do this. Inheritance is based off of instance methods in C# and has no equivalent feature for static methods. Another way to implement this pattern though is to require a lambda in lieu of a static method.
For example (you mentioned the actual type was A<TFoo, TBar>)
void UseIt<TFoo, TBar>(A<TFoo, TBar> p, Func<SomeData, TBar> func) {
TBar b = func();
...
}
The consumer doesn't care if Create is static, instance or even called create. Generally all they care about is having a function which takes a SomeData and returns a TBar. Delegates fit this pattern exactly.
I have following classes:
public abstract class CustomerBase
{
public long CustomerNumber { get; set; }
public string Name { get; set; }
}
public abstract class CustomerWithChildern<T> : CustomerBase
where T: CustomerBase
{
public IList<T> Childern { get; private set; }
public CustomerWithChildern()
{
Childern = new List<T>();
}
}
public class SalesOffice : CustomerWithChildern<NationalNegotiation>
{
}
The SalesOffice is just one of few classes which represent different levels of customer hierarchy. Now I need to walk through this hierarchy from some point (CustomerBase). I can't figure out how to implement without using reflection. I'd like to implement something like:
public void WalkHierarchy(CustomerBase start)
{
Print(start.CustomerNumber);
if (start is CustomerWithChildern<>)
{
foreach(ch in start.Childern)
{
WalkHierarchy(ch);
}
}
}
Is there any chance I could get something like this working?
The solution based on suggested has-childern interface I implemented:
public interface ICustomerWithChildern
{
IEnumerable ChildernEnum { get; }
}
public abstract class CustomerWithChildern<T> : CustomerBase, ICustomerWithChildern
where T: CustomerBase
{
public IEnumerable ChildernEnum { get { return Childern; } }
public IList<T> Childern { get; private set; }
public CustomerWithChildern()
{
Childern = new List<T>();
}
}
public void WalkHierarchy(CustomerBase start)
{
var x = start.CustomerNumber;
var c = start as ICustomerWithChildern;
if (c != null)
{
foreach(var ch in c.ChildernEnum)
{
WalkHierarchy((CustomerBase)ch);
}
}
}
You could move the WalkHierarchy method to the base class and make it virtual. The base class implementation would only process the current node. For the CustomerWithChildern<T> class, the override would do an actual walk.
Try this:
if(start.GetType().GetGenericTypeDefinition() == typeof(CustomerWithChildern<>))
I believe that you want to make the lookup for the determination of doing to the walk an interface.
So maybe add an "IWalkable" interface that exposes the information needed to do the walk, then you can create your method checking to see if the passed object implements the interface.
"Is" and "As" only work on fully qualified generic types.
See this MSDN discussion for details including workarounds.
The most common workaround I've seen is to add an interface to the mix that your CustomerWithChildren could implement, and check for that interface.
I think everyone hits this "issue" when first working with generic classes.
Your first problem is hinted at in your question phrasing: an open generic type is NOT the base class to a closed one. There is no OO relationship here, at all. The real base class is CustomerBase. An "open" generic type is like a half-completed class; specifying type arguments "closes" it, making it complete.
While you can do:
Type t = typeof(CustomerWithChildern<>)
the condition
typeof(CustomerWithChildern<>).IsAssignableFrom(CustomerWithChildern<Foo>)
will always be False.
-Oisin
Explicitly with that method, no. However you can achieve the same functionality with an interface. In fact, you could just have your generic class implement IEnumerable. It's also worth noting that your class should also have "where T : CustomerBase" in order to ensure type safety.