简体   繁体   中英

IDescription interface using generics and extension methods

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);
   }
}

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);

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);
    }
} 

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?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM