0

Based on this topic: C# - Multiple generic types in one list

Please consider this code:

public abstract class Metadata
{
}

public class Metadata<T> : Metadata
{
    public string Name {set; get;}
}

public class MetaDataCollection
{
    public void DoSomeThing()
    {
        List<Metadata> metadataObjects = new List<Metadata>
        {
            new Metadata<int>() { Name = "Name 1"},
            new Metadata<bool>() { Name = "Name 2"},
            new Metadata<double>() { Name = "Name 3"},
        };

        foreach(vat item in metadataObjects)
        {
            item.Name ??????
        }
    }
}

in above code how I can access to Name property?

Thanks

EDIT 1)

Thanks @BWA. But I have a generic property:

public class Metadata<T> : Metadata
{
    public override string Name {set; get;}

    public List<T> Some {set; get;} <-----
}

and I can't declare it in base abstract class. For that property what I can do?

Arian
  • 12,793
  • 66
  • 176
  • 300
  • 2
    Pull the property to `Metadata` and have `Metadata` inherit from it. Or convert `Metadata` to an Interface with a `Name` property. Right now, `Metadata` and `Metadata` are unrelated – Panagiotis Kanavos Oct 03 '18 at 14:50
  • You can't, because `Metadata` doesn't have that property. Instead of going to ask [multiple (duplicate) questions](https://stackoverflow.com/questions/52628636/check-base-class-for-different-generic-objects) about the same problem, try properly explaining what you're trying to do. – CodeCaster Oct 03 '18 at 14:51
  • 1
    BTW this isn't related to C# 7 or generics, it's just inheritance – Panagiotis Kanavos Oct 03 '18 at 14:52
  • @Arian It is preferred if you can post separate questions instead of combining your questions into one. That way, it helps the people answering your question and also others hunting for at least one of your questions. Thanks! – Panagiotis Kanavos Oct 03 '18 at 15:05
  • Possible duplicate of [Using generics in abstract classes](https://stackoverflow.com/questions/2359540/using-generics-in-abstract-classes) – BWA Oct 03 '18 at 15:09
  • This question, the deleted one and the `Metadata` name make me wonder whether you really want MVC's or EF's helpers and data annotations? – Panagiotis Kanavos Oct 03 '18 at 15:16

3 Answers3

3

Your code doesn,t compile.

Metadata, Metadata<T>, Metadata<int> ...

Each are different type. Generic types isn't inheritance. You cann't do this in this way.

You can do in this way:

using System.Collections.Generic;

public abstract class Metadata
{
    public abstract string Name { set; get; }
}

public class Metadata<T> : Metadata
{
    public override string Name {set; get;}
}

public class MetaDataCollection
{
    public void DoSomeThing()
    {
        List<Metadata> metadataObjects = new List<Metadata>
        {
            new Metadata<int>() { Name = "Name 1"},
            new Metadata<bool>() { Name = "Name 2"},
            new Metadata<double>() { Name = "Name 3"},
        };

        foreach(Metadata item in metadataObjects)
        {
            string s = item.Name;
        }
    }
}

At first Metadata<T> must inherit from Metadata. And then inheritance can work.

BWA
  • 5,672
  • 7
  • 34
  • 45
1

Right now, Metadata and Metadata are unrelated. They have no inheritance relationship, just similar names.

One option is to pull the Name property to Metadata and have Metadata inherit from it:

public abstract class Metadata
{
    public string Name {set; get;}
}

public class Metadata<T>:Metadata
{
    //public string Name {set; get;}
}

The other option is to convert Metadata to an interface with a Name property :

public interface IMetadata
{
    string Name {set; get;}
}

public class Metadata<T>:IMetadata
{
    public string Name {set; get;}
}

Change the test code to use the correct base class, eg :

{
    var metadataObjects = new List<Metadata>
    {
        new Metadata<int>() { Name = "Name 1"},
        new Metadata<bool>() { Name = "Name 2"},
        new Metadata<double>() { Name = "Name 3"},
    };

or

    var metadataObjects = new List<IMetadata>
    {
        new Metadata<int>() { Name = "Name 1"},
        new Metadata<bool>() { Name = "Name 2"},
        new Metadata<double>() { Name = "Name 3"},
    };

In both cases, the loop remains the same :

    foreach(var item in metadataObjects)
    {
        Console.WriteLine(item.Name);
    }
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
  • 1
    @Arian that's a *different* question. Please post one, *complete* question. – Panagiotis Kanavos Oct 03 '18 at 15:04
  • Yes you are right. But Sorry, I want to forget about the generic properties – Arian Oct 03 '18 at 15:05
  • Post a different question. This one has been answered. In fact, unless you want to use `Some` inside the loop, the generic property won't matter. – Panagiotis Kanavos Oct 03 '18 at 15:06
  • @Arian or rather, explain what you really want to do, not how you try to implement it. DataTables have metadata, so does Entity Framework. You could reuse their techniques or even use the metadata classes directly – Panagiotis Kanavos Oct 03 '18 at 15:09
  • @Arian check how HTML Helpers in MVC, or model configuration classes in EF work for example. You pass an *expression* as a parameter that the helper or model builder can use to find the property you want to display or configure. Once they do that, they can check for any data annotation attributes like `DisplayAttribute` – Panagiotis Kanavos Oct 03 '18 at 15:13
0

i don't if this is what you want but its gonna give you the result you ask.

public class Metadata
{
   public Type type { get; set; }
   public string Name { set; get; }
}

public class MetaDataCollection
{
   public void DoSomeThing()
   {
      List<Metadata> metadataObjects = new List<Metadata>
      {
         new Metadata() { Name = "Name 1", type = typeof(int)},
         new Metadata() { Name = "Name 2", type = typeof(bool)},
         new Metadata() { Name = "Name 3", type = typeof(double)},
      };

      foreach (Metadata item in metadataObjects)
      {
         item.Name..
      }
   }
}
trksyln
  • 136
  • 10