如何定义/创建一个泛型类的类属性

huangapple go评论70阅读模式
英文:

How to define/create a Class property of a Generic Class

问题

我有模型类(AModel,BModel,...,ZModel),可以在通用类(Generic<IModel>)中使用。

public class AModel : IModel
{
    public string id { get; set; }
    public string specialPropsOfA { get; set; }

    public string DoWorkWithSpecialProps()
    {
        throw new NotImplementedException(); // do work with on specialsprops
    }
}

public interface IModel
{
    public string id { get; set; }

    public string DoWorkWithSpecialProps();
}

public class Generic<T> where T : IModel
{
    public List<T> UseGeneric(string uid)
    {
        //Doing work with Model.id
        return new List<T>();
    }
}

我需要遍历A - Z并执行相同的操作。

这是我目前实现解决方案的方式:

// 不符合DRY原则
Generic<AModel> AGeneric = new();
var A = AGeneric.UseGeneric("axx");

A.ForEach(a => { var doingWork = a.DoWorkWithSpecialProps(); });

Generic<BModel> BGeneric = new();
var B = BGeneric.UseGeneric("bxx"); // 与A相同的操作

B.ForEach(b => { var doingWork = b.DoWorkWithSpecialProps(); /*Do same work as a*/ });
// ...

你如何实现一个包含通用方法的类(集合),以遍历它们,而不重复自己?

// 符合DRY原则
List<Collection> collections = new()
{
    new()
    {
        Generic = new Generic<AModel&gt(),  // 错误:Generic<AModel> != Generic<IModel>
        uid     = "axx"
    },
    new()
    {
        Generic = new Generic<BModel&gt(),  // 错误:Generic<BModel> != Generic<IModel>
        uid     = "bxx"
    }
};

collections.ForEach(c =>
{
    var X = c.Generic.UseGeneric(c.uid);
    X.ForEach(_ => { var doingWork = x.DoWorkWithSpecialProps(); });
});

public class Collection
{
    public Generic<IModel> Generic { get; set; } // 我应该做什么更改以允许任何Generic方法
    public string uid { get; set; }
}

我尝试将Collection.Generic设置为动态类型(需要将var c强制转换为Generic<IModel>),但这只是移动了问题。

我将集合设为通用类,但这需要List<Collection<IModel>>,这同样只是移动了问题。我还创建了IGeneric,这是Generic类的一个实现,但仍然需要IModel。我应该声明什么类型的Collection.Generic,以允许我将其设置为Generic<AModel>Generic<ZModel>

英文:

I have model classes (AModel, BModel, ..., ZModel) that can be used in a generic class (Generic<IModel>).

public class AModel : IModel
{
    public string id { get; set; }
    public string specialPropsOfA { get; set; }

    public string DoWorkWithSpecialProps()
    {
        throw new NotImplementedException(); // do work with on specialsprops
    }
}

public interface IModel
{
    public string id { get; set; }

    public string DoWorkWithSpecialProps();
}

public class Generic<T> where T : IModel
{
    public List<T> UseGeneric(string uid)
    {
        //Doing work with Model.id
        return new List<T>();
    }
}

I need go thru A - Z and do the same operation

This is currently how I implemented the solution

// Does not comply with DRY
Generic<AModel> AGeneric = new();
var A = AGeneric.UseGeneric("axx");

A.ForEach(a => { var doingWork = a.DoWorkWithSpecialProps(); });

Generic<BModel> BGeneric = new();
var B = BGeneric.UseGeneric("bxx"); // same operation as a

B.ForEach(b => { var doingWork = b.DoWorkWithSpecialProps(); /*Do same work as a*/ });
...

How would you implement a class (collection) to contain the generic method to iterate over and not repeat myself?

// Would comply with DRY
List<Collection> collections = new()
{
    new()
    {
        Generic = new Generic<AModel>(),  // Error: Generic<AModel> != Generic<IModel>
        uid     = "axx"
    },
    new()
    {
        Generic = new Generic<BModel>(),  // Error: Generic<BModel> != Generic<IModel>
        uid     = "bxx"
    }
};

collections.ForEach(c =>
{
    var X = c.Generic.UseGeneric(c.uid);
    X.ForEach(_ => { var doingWork = x.DoWorkWithSpecialProps(); });
});


public class Collection
{
    public Generic<IModel> Generic { get; set; } // What do I change to allow any Generic method
    public string uid { get; set; }
}

I've tried setting Collection.Generic to be Type dynamic (I would need to cast var c to Generic<IModel>) which only moved the problem.

I have made collection a generic class but that required the List<Collection<IModel>> which again only move the problem. I have also made IGeneric which is an implementation of the Generic class but that would still require IModel. What type do I declare Collection.Generic to allow me to set it to Generic<AModel> or to Generic<ZModel>?

答案1

得分: 1

我提出并目前正在使用的解决方案是创建一个通用类并使用它调用每个模型。

```csharp
public void WorkEachModel<T>(string uid) where T : IModel
{
    var GenericFunc = new Generic<T>();
    var A = GenericFunc.UseGeneric(uid);
    A.ForEach(a => { var doingWork = a.DoWorkWithSpecialProps(); });
}

而不是创建一个“List”并循环,你可以使用每个模型调用它。

WorkEachModel<AModel>("axx");
WorkEachModel<BModel>("bxx");
...
WorkEachModel<ZModel>("zxx");

一个主要限制是它不是一个列表,所以你不能推入或弹出模型。例如,如果我不想使用XModel,我会将其从列表中弹出(或者在开始时不包括它),然后运行循环,它将经过A-Z并排除X(但你可以有一个if语句检查是否要在执行WorkEachModel("Xxx")之前运行X)。不管怎样,问题是出在DRY上,这个方法解决了它。


<details>
<summary>英文:</summary>

The solution I came up with and currently using was to make a generic class and call each Model with it.

public void WorkEachModel<T>(string uid) Where T : IModel
{
var GenericFunc = new Generic<T>()
var A = GenericFunc.UseGeneric(uid);
A.ForEach(a => { var doingWork = a.DoWorkWithSpecialProps(); });
}


And instead of creating a &quot;List\&lt;collection\&gt;&quot; and looping you would call it with each model.

WorkEachModel<AModel>("axx");
WorkEachModel<BModel>("bxx");
...
WorkEachModel<ZModel>("zxx");

One major limitation is it&#39;s not a list so you cannot push or pop Models. For Example, I don&#39;t want to use XModel so I pop (or not include it at the start) it from the List and then run thru the loop which will go thru A-Z and exclude X. (But you can have an if statement checking if you want to run X before executing WorkEachModel\&lt;XModel\&gt;(&quot;Xxx&quot;)).
Anyways the issue was with DRY and this solved it.

</details>



# 答案2
**得分**: 0

创建一个基础的抽象类
这是我的架构
接口:
```csharp
public interface IModel
{
    public string id { get; set; }

    public string DoWorkWithSpecialProps();
}

基础模型

public abstract class ModelBase : IModel
{
    public string id { get; set; }    

    public string DoWorkWithSpecialProps()
    {
        throw new NotImplementedException();
    }
}

AModel

public class AModel : ModelBase
{    
    public string specialPropsOfA { get; set; }    
}
英文:

Create a base abstract class
this is my architect
interface :

public interface IModel
{
    public string id { get; set; }

    public string DoWorkWithSpecialProps();
}

Model de base

public abstract class ModelBase : IModel
{
    public string id { get; set; }    

    public string DoWorkWithSpecialProps()
    {
        throw new NotImplementedException();
    }
}

AModel

public class AModel : ModelBase
{    
    public string specialPropsOfA { get; set; }    
}

huangapple
  • 本文由 发表于 2023年3月8日 15:09:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/75670194.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定