IDescription interface using generics and extension methods - c#

I am trying to implement an IDescription Interface. Basic purpose of this interface is that I have many different classes that have a list of multilingual descriptions and I want the the basic AddDescription EditDescription and some other basic behaviours to be defined by the interface and not implemented by the classes individually that inherits the interface. I am trying to assign the behavior to the interface using extension methods.
I have some road blocks such as how do I access the descriptions collection of the entity that I am passing on to the IDescription interface (entity.Descriptions.Add)?
I am very new to generics, extension methods, anonymous types etc so please bear with me with my misunderstandings of how these are used. Will appreciate if you can help me correct the below code. I wrote it to give the idea of what I am trying to achieve, it obviously fundamental errors in it. Thanks
public class Company : IDescription<Company, CompanyDescription>
{
public IList<CompanyDescription> Desriptions { get; set; }
}
public class Location : IDescription<Location, LocationDescription>
{
public IList<LocationDescription> Desriptions { get; set; }
}
public interface IDescription<eT, dT>
{
void AddDescription(eT, string text);
void EditDescription(eT, dT, string text);
}
public static DescriptionInterfaceExtensions
{
public static void AddDescription(this IDescription<eT, dT> description, eT entity, string text)
{
dT newDescription = new dT(text);
entity.Descriptions.Add(newDescription);
}
}

Another possible rewrite that should work is to remove the Add/Edit methods from the interface and simply provide the required IList in the interface. Then, for ease of use, you can use the extension methods to make it easier.
I'm not saying this example is a great use of generics or extension methods, but it will work:
public class CompanyDescription : IDescription { public string Text { get; set; } }
public class LocationDescription : IDescription { public string Text { get; set; } }
public class Company : IHaveDescriptions<CompanyDescription>
{
public IList<CompanyDescription> Desriptions { get; set; }
}
public class Location : IHaveDescriptions<LocationDescription>
{
public IList<LocationDescription> Desriptions { get; set; }
}
public interface IDescription
{
string Text { get; set; }
}
public interface IHaveDescriptions<T>
where T : class, IDescription, new()
{
IList<T> Desriptions { get; set; }
}
public static class DescriptionInterfaceExtensions
{
public static void AddDescription<T>(this IHaveDescriptions<T> entity, string text)
where T : class, IDescription, new()
{
T newDescription = new T();
newDescription.Text = text;
entity.Desriptions.Add(newDescription);
}
public static void EditDescription<T>(this IHaveDescriptions<T> entity, T original, string text)
where T : class, IDescription, new()
{
T newDescription = new T();
newDescription.Text = text;
entity.Desriptions.Remove(original);
entity.Desriptions.Add(newDescription);
}
}

I your example it seems the contract is that objects that have a description store a list of descriptions. So, to avoid having to declare Add and Remove methods in the classes directly, you could do something like this:
Interfaces
public interface IDescription<T>
{
}
public interface IHasDescription<THasDescription, TDescription>
where THasDescription : IHasDescription<THasDescription, TDescription>
where TDescription : IDescription<THasDescription>
{
IList<TDescription> Descriptions { get; }
}
Concrete implementations
public class CompanyDescription : IDescription<Company>
{
}
public class Company : IHasDescription<Company, CompanyDescription>
{
private readonly IList<CompanyDescription> descriptions;
public IList<CompanyDescription> Descriptions
{
get { return this.descriptions; }
}
}
Extension methods
public static class DescriptionExtensions
{
public static void AddDescription<THasDescription, TDescription>(
this THasDescription subject,
TDescription description)
where THasDescription : IHasDescription<THasDescription, TDescription>
where TDescription : IDescription<THasDescription>
{
subject.Descriptions.Add(description);
}
}
But I don't think it's worth to do this just to have
mycompany.AddDescription(mydescription);
instead of
mycompany.Descriptions.Add(mydescription);

You can't add interface implementations to classes using extension methods, although that seems to be what you are trying to do.
The purpose of extension methods is to add behavior to existing types (classes or interfaces).
The problem with your code is that you declare that Company and Location should implement the IDescription interface; yet they don't. They have no AddDescription or EditDescription methods, so that's not going to work.
Why don't you instead define a concrete generic Description class and attach that class to Company and Location?

Related

How to make a re-usable method of type T

I have a method as below
List<Customer> GetCusts = dataContext.Customers;
The customers table has a field called IsValued so i can do something like this
foreach (var c in GetCusts)
{
if(c.IsValued)
{
// do something
}
}
I have a products table doing the exact same thing also with the same column name
List<Product> GetProds = dataContext.Products;
foreach (var p in GetProds)
{
if(p.IsValued)
{
// do something
}
}
I thought to turn this into a Generic method (or better a class), so i can pass in a generic list a bit like
foreach (var p in GetData) // GetData could be a List<t> but of course i cant cast it.
{
if (p.IsValued)
{}
}
but of course IsValued does not exist. I know the reason why (due to it being a generic type) but after researching around to see if its possible i couldnt get a decent example and test it out or maybe i just didnt understand. Can anyone advise how this could be possible or lead me to an article to achieve this?
Edit 1
My attempt so far in a class, it could be wrong but to give an idea in case im on the wrong path. I assume i need a property of IsValued (which doesnt have to be of a bool value) in the GenericValue class?
public interface ICustomGenerics<T>
{
IEnumerable<T> GetData();
}
public class GenericValue<T> : ICustomGenerics<T> where T : class
{
public IEnumerable<T> GetAll()
{
_entities.
}
}
Here is how you can use an interface:
public interface IValued {
bool IsValued { get; set; }
}
public class Customer : IValued {
public bool IsValued { get; set; }
}
public class Product : IValued {
public bool IsValued { get; set; }
}
public void filterData<T>(List<T> data) where T: IValued {
foreach (var d in data) {
if (d.IsValued) {
}
}
}
As others pointed out you can either pick a base class and derive from that, or you can use an interface. I'd rather go with the interface in this case.
Assuming you are using Entity Framework, you can use a partial classes to apply your interface:
public interface IValuable
{
bool IsValued { get; set; }
}
and you'd have partial classes like:
public partial class Customer : IValuable
{
// IValuable implementation
public bool IsValued { get; set; }
}
public partial class Product : IValuable
{
// IValuable implementation
public bool IsValued { get; set; }
}
Now you can have a processor / service class that accepts these as generics with a condition that they should all implement this interface:
public class Processor<T> where T : IValuable
{
public Something Process(T parameter)
{
foreach (var p in GetData)
{
if (p.IsValued)
{
// Do stuff
}
}
}
}
Since you declared your generic to have IValuable implementation, the code below will know IsValuable is a member.
I suggest this approach over base classes because interfaces are best used this way to define common behaviour. You can even see the same pattern in the framework, IDisposable (which implements Dispose()) and IEnumerable / IEnumerator (which implements things like GetEnumerator(), MoveNext() etc) are two most common examples.

C# OOP Cast interface parameter to concrete type

i'm trying to build a sort of framework for some base process in an app. There is some common behavior where i have to execute some operations but these operations are different depending on some scenarios. I have done something i'm not sure if it's considered a bad practice to make something like this:
public interface IMyDto
{
string makerIdentifier { get; set; }
}
public class DtoOne:IMyDto
{
public string makerIdentifier { get; set; }
//Custom properties for ConcreteOne
}
public class DtoTwo:IMyDto
{
public string makerIdentifier { get; set; }
//Custom properties for ConcreteTwo
}
public abstract class AbstractMaker
{
public abstract void DoSomething(IMyDto myInterface);
}
public class ConcreteMakerOne:AbstractMaker
{
public override void DoSomething(IMyDto myInterface)
{
var concrete = myInterface as DtoOne;
// If concrete is not null..do stuff with DtoOne properties
}
}
public class ConcreteMakerTwo : AbstractMaker
{
public override void DoSomething(IMyDto myInterface)
{
var concrete = myInterface as DtoTwo;
// If concrete is not null..do stuff with DtoTwo properties
}
}
public class Customer
{
public void MakeSomething(IMyDto myDto)
{
var maker = GetMaker();
maker.DoSomething(myDto);
}
private AbstractMaker GetMaker()
{
//Stuff to determine if return ConcreteOne or ConcreteTwo
}
}
The code im not happy with is the:
var concrete = myInterface as DtoOne;
I would appreciate a lot if someone could give me some advide or tips about a pattern or good oop practice for this scenario.
It's not clear what all of your use cases are, but one option might be generics:
public abstract class AbstractMaker<T> where T:IMyDto
{
public abstract void DoSomething(T myInterface);
}
public class ConcreteMakerTwo : AbstractMaker<DtoTwo>
{
public override void DoSomething(DtoTwo myInterface)
{
// now you are certain that myInterface is a DtoTwo
}
}
I am not sure if I understand correctly what are you asking about, but why not just put method DoSomething in IMyDto and implement it differently in DtoOne, DtoTwo, etc.? There would be only one Maker and would always call the same method.

Accessing base class function from secondarily derived functions

I seriously hope my title is clear enough. If it's not I'm happy to have better suggestions.
The situation is thus (variable types are just examples):
public abstract class A
{
public virtual string X(string arg)
{
return "blarg";
}
}
public class CommonProperties : A
{
public string foof { get; set;} = "widget";
public string yay { get; set; }
public override string X(string arg)
{
return base.X(arg);
}
}
public class B : CommonProperties
{
public string UniqueProperty1 { get; set; }
public override string X(string arg)
{
return base.X(arg);
}
}
public class C : CommonProperties
{
public string UniqueProperty2 { get; set; }
public override string X(string arg)
{
return base.X(arg);
}
}
class D : A
{
public override string X(string arg)
{
return base.X(arg);
}
}
}
I'm generalizing my problem. This is not my actual code.
The problem is that C# does not allow multiple inheritance for abstract classes, interfaces don't allow for default code (yet) nor do they allow for default initializers.
I'd like CommonProperties to be derived from the abstract class and the classes derived from it (classes B and C) to be able to directly access the original abstract class's implementation of the X function rather than the overriding CommonProperties implementation of it. I've tried doing base.base.X(arg) but that didn't work. The next best way would be to have classes B and C derived from both class A and class CommonProperties but C# doesn't allow this. Making class A an interface won't work because I have a large number of classes derived from it and that would mean I'd have to copy the needed code into every. single. one. I can't make CommonProperties an interface because of that restriction on default values. I could move the common properties into their derived classes but that defeats code reuse (I may need to add additional properties over time and that would mean updating would be slower and more prone to error, etc.)
I can't wait until C# 8.0 (theoretically) having a default implementation of functions. If I can get B and C to directly access the hidden A.X() function that is hidden by the CommonProperties.X() function that would be a good workaround. I suspect that latter solution is possible with reflection (in fact in my project the A class is doing just that so the topic isn't difficult for me), but I'd like to know if there was a more direct method.
Edit: Adding one more class to clarify the issue better. I forgot that CommonProperties was supposed to inherit from A and also show that other classes directly inherit from A.
You need to add a non virtual method to class A that calls the A.X implementation. The method name includes the class name, I used double underscore to separate method name and class name.
public abstract class A
{
public virtual string X(string arg)
{
return "blarg";
}
public string X__A(string arg)
{
return X(arg);
}
}
public class CommonProperties : A
{
public string foof { get; set;} = "widget";
public string yay { get; set; }
public override string X(string arg)
{
return "comarg";
}
}
public class B : CommonProperties
{
public string UniqueProperty1 { get; set; }
public override string X(string arg)
{
return X__A(arg);
}
}

Generic Interface inheriting Non-Generic One C#

This is class design question.
I have main abstract class
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions {get;};
}
public interface IRestriction{}
public interface IRestriction<T>:IRestriction where T:struct
{
T Limit {get;}
}
public TimeRestriction:IRestriction<TimeSpan>
{
public TimeSpan Limit{get;set;}
}
public AgeRestriction:IRestriction<int>
{
public int Limit{get;set;}
}
public class BlockRule:AbstractBlockRule
{
public virtual List<IRestriction> Restrictions {get;set;}
}
BlockRule rule=new BlockRule();
TimeRestriction t=new TimeRestriction();
AgeRestriction a=new AgeRestriction();
rule.Restrictions.Add(t);
rule.Restrictions.Add(a);
I have to use non-generic Interface IRestriction just to avoid specifying generic type T in main abstract class. I'm very new to generics. Can some one let me know how to better design this thing?
Your approach is typical (for example, IEnumerable<T> implements IEnumerable like this). If you want to provide maximum utility to consumers of your code, it would be nice to provide a non-generic accessor on the non-generic interface, then hide it in the generic implementation. For example:
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions { get; set; }
}
public interface IRestriction
{
object Limit { get; }
}
public interface IRestriction<T> : IRestriction
where T:struct
{
// hide IRestriction.Limit
new T Limit {get;}
}
public abstract class RestrictionBase<T> : IRestriction<T>
where T:struct
{
// explicit implementation
object IRestriction.Limit
{
get { return Limit; }
}
// override when required
public virtual T Limit { get; set; }
}
public class TimeRestriction : RestrictionBase<TimeSpan>
{
}
public class AgeRestriction : RestrictionBase<TimeSpan>
{
}
public class BlockRule : AbstractBlockRule
{
public override List<IRestriction> Restrictions { get; set; }
}
I also showed using a base restriction class here, but it is not required.
The runtime treats IRestriction<TimeSpan> and IRestriction<int> as different distinct classes (they even have their own set of static variables). In your case the only classes common to both IRestriction<TimeSpan> and IRestriction<int> in the inheritance hierarchy are IRestriction and object.
So indeed, having a list of IRestriction is the only sensible way to go.
As a side note: you have a property Limit in there that you might want to access regardless of whether you're dealing with an IRestriction<TimeSpan> or IRestriction<int>. What I would do in this case is to define another property object Limit { get; } on IRestriction, and hide it in the actual implementation. Like this:
public interface IRestriction
{
object Limit { get; }
}
public interface IRestriction<T> : IRestriction
where T : struct
{
new T Limit { get; set; }
}
public class TimeRestriction : IRestriction<TimeSpan>
{
public TimeSpan Limit { get; set; }
// Explicit interface member:
// This is hidden from IntelliSense
// unless you cast to IRestriction.
object IRestriction.Limit
{
get
{
// Note: boxing happens here.
return (object)Limit;
}
}
}
This way you can access Limit as object on all your IRestriction when you don't care what type it is. For example:
foreach(IRestriction restriction in this.Restrictions)
{
Console.WriteLine(restriction.Limit);
}
Interfaces are contracts that need to be followed by the entity that implements the contract.
You have created two contract with the same name IRestriction
As far as I can see, what you are basically may need is a flag for classes that can be restricted, which should implement the IRestriction non-generic interface.
The second interface seems to be restrictable objects that also contain a limit property.
Hence the definition of the second IRestriction interface can be ILimitRestriction or whatever name suits your business needs.
Hence ILimitRestriction can inherit from IRestriction which would mark classes inheriting ILimitRestriction still objects of IRestriction
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions {get;};
}
public interface IRestriction{}
public interface IRestrictionWithLimit<T>:IRestriction where T:struct
{
T Limit {get;}
}
public TimeRestriction:IRestrictionWithLimit<TimeSpan>
{
public TimeSpan Limit{get;set;}
}
public AgeRestriction:IRestrictionWithLimit<int>
{
public int Limit{get;set;}
}
public class BlockRule:AbstractBlockRule
{
public virtual List<IRestriction> Restrictions {get;set;}
}

Requiring interface implementations to have a static Parse method

I've got a minimal interface, and will be dealing with a collection of objects whose classes implement this interface. The collection (along with its associated functionality) doesn't care about any of the details of these objects beyond their name, the ability to convert them to XML, and the ability to parse them from XML.
Future implementations of the interface will do a lot more with the elements of the collection, and will obviously implement their own Parse and ToXml methods (which will be used by the collection to parse these items appropriately when encountered).
Unfortunately, I am unable to list a static Parse method in the interface (I've read these three questions). It doesn't make sense to me to have a Parse method require an instance. Is there any way to require that all implementations of the interface have a static Parse method?
public interface IFoo
{
string Name { get; }
string ToXml();
static IFoo Parse(string xml); // Not allowed - any alternatives?
}
You can't do that. And static methods aren't polymorphic anyway, so it wouldn't make too much sense.
What you want here is some kind of factory pattern.
Assuming Parse takes a string and turns it into a fully-populated object, how about a Hydrate method instead, like:
interface IFoo {
string Name { get; set; }
int Age { get; set; }
void Hydrate(string xml);
}
class Foo : IFoo {
public string Name { get; set; }
public int Age { get; set; }
public void Hydrate(string xml) {
var xmlReader = ...etc...;
Name = xmlReader.Read(...whatever...);
...etc...;
Age = xmlReader.Read(...whatever...);
}
}
void Main() {
IFoo f = new Foo();
f.Hydrate(someXml);
}
Or Fluent it up a bit:
public IFoo Hydrate(string xml) {
// do the same stuff
return this;
}
void Main() {
IFoo f = new Foo().Hydrate(someXml);
}
The only alternative that comes to my mind is to use an abstract class instead of an interface here. However you won't be able to override static method's behaviour in child classes anyway.
You can achieve somewhat similar behaviour using Factory pattern and requiring classes implementing IFoo to have a reference to that Factory (which can be injected in them via constructor injection):
public interface IFoo
{
string Name { get; }
string ToXml();
IFooFactory FooFactory { get; }
}
public interface IFooFactory
{
IFoo Parse(string xml);
}
I would extract all serialization-related methods into a different interface. Please consider the following example:
public interface IFoo
{
string Name { get; }
IFooSerializer GetSerializer(string format);
}
public enum FooSerializerFormat { Xml, Json };
public interface IFooSerializer
{
string Serialize(IFoo foo);
IFoo Deserialize(string xml);
}
public class Foo : IFoo
{
public string Name { get; }
public IFooSerializer GetSerializer(FooSerializerFormat format)
{
case FooSerializerFormat.Xml:
return new FooXmlSerializer();
case FooSerializerFormat.Json:
return new FooJsonSerializer();
}
}
public class FooXmlSerializer : IFooSerializer { /* Code omitted. */ }
public class FooJsonSerializer : IFooSerializer { /* Code omitted. */ }
Maybe this way?
public interface IFoo
{
string Name { get; }
string ToXml();
IFoo Parse(string xml);
}
public abstract class AFoo : IFoo
{
public string Name { get; set; }
public string ToXml() { };
public IFoo Parse(string xml) { return AFoo.StaticParse(xml); };
public static IFoo StaticParse(string xml) { }; // implement one here
}
Even if the above could be a solution I would encourage you to use the abstact factory and/or template method instead. See Template Method Pattern instead. Another Option might be the usage of an Extension method if you wan't to share it among several implementations.
Broadly speaking, I have been known (on occasion) to use Extension methods for stuff like this:
public interface IFoo
{
string Name {get;}
string ToXml();
}
public class Foo : IFoo
{
public Foo(string name)
{
Name = name;
}
public string Name {get; private set;}
public string ToXml()
{
return "<derp/>";
}
}
So that's the instance stuff, let's handle the "static" bit:
public static class FooExts
{
public static IFoo Parse(this string xml)
{
return new Foo("derp");
}
}
And a test:
void Main()
{
var aFoo = "some xml".Parse();
Console.WriteLine(aFoo.ToXml());
}
As #Jim mentions, there is the case where you don't want a Foo back, in which case you might use something like:
public static T Parse<T>(
this string xml,
Func<string, IFoo> useMeUseMe = null)
where T:IFoo
{
if(useMeUseMe == null)
useMeUseMe = (x => new Foo(x));
return (T)useMeUseMe("derp");
}
Alas, we must now tell the method what we want when we deviate from the "norm":
var aFoo = "some xml".Parse<Foo>();
Console.WriteLine(aFoo.ToXml());
var aBar = "some xml".Parse<Bar>(s => new Bar(s));
Console.WriteLine(aBar.ToXml());

Categories