C# 在泛型/非泛型情况下操纵类成员

C# 在泛型/非泛型情况下操纵类成员,c#,generics,inheritance,C#,Generics,Inheritance,假设您有一个非泛型Foo和泛型类Foo。在非泛型类中,有一个非泛型FooBar类型的成员变量,同样,在泛型类中也有一个FooBar类型的成员变量 public class Foo { protected FooBar SomeVar; public void DoSomething() { // Manipulate SomeVar here } } public class Foo<T>: Foo where T: SomeObject

假设您有一个非泛型Foo和泛型类Foo。在非泛型类中,有一个非泛型FooBar类型的成员变量,同样,在泛型类中也有一个FooBar类型的成员变量

public class Foo
{
   protected FooBar SomeVar;

   public void DoSomething()
   {
       // Manipulate SomeVar here 
   }
}

public class Foo<T>: Foo where T: SomeObject
{
  protected new FooBar<T> SomeVar;
}
公共类Foo
{
受保护的FooBar-SomeVar;
公共无效剂量测定法()
{
//在这里操纵SomeVar
}
}
公共类Foo:Foo其中T:SomeObject
{
受保护的新FooBar SomeVar;
}
另外,FooBar是从代码中未显示的FooBar派生的

假设在非泛型类中有一个方法,它使用成员变量SomeVar执行一些数据操作。现在的问题是,如果实例化了泛型类Foo,那么在非泛型类中实现的方法只引用了非泛型SomeVar,而不了解泛型变量

现在看来,解决这个问题的唯一方法是重写泛型类中的DoSomething方法,这将允许它了解泛型变量

我猜这种方法的问题在于逻辑是从非泛型类复制到泛型类的。这个问题还有其他解决办法吗

更新: 我已经更新了类,使其更符合我的问题:

public abstract class BaseObject
{
   // Abstract class that handles how the object is loaded when querying database for an object
}

public class Name : BaseObject
{
   public string FirstName {get;set;} 
   public string LastName {get;set;} 
   public Date DOB {get;set;}
}

public interface IData
{
   List<string> SearchFields;
   string timestamp;
   Search search; // Search is a class that will query the database for a given object and because this is a non generic version, it'll bring back a list of base object
}

public interface IData<T> : IData, where T: BaseObject
{
   Search<T> search; // Bring back a list of <T>
}

public class BrowseData: IData
{
   Search search;
} 

public class BrowseData<T>: BrowseData, IData<T> where T: BaseObject
{
   Search<T> search;
}

public class BrowseBuilder
{
   protected BrowseData Data;
   public BrowseBuilder(BrowseData data)
   {
      Data = data;
   }

   public void DoRender()
   {
       // Using the data provided does the rendering
   }
}

public class BrowseBuilder<T>: BrowseBuilder where T: BaseObject
{
   protected new BrowseData<T> Data;
   public BrowseBuilder(BrowseData<T> data)
   {
      Data = data;
   }
}
公共抽象类BaseObject
{
//处理在查询数据库中的对象时如何加载对象的抽象类
}
公共类名:BaseObject
{
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共日期DOB{get;set;}
}
公共接口IData
{
列出搜索字段;
字符串时间戳;
Search Search;//Search是一个类,它将在数据库中查询给定对象,因为这是一个非泛型版本,它将返回一个基本对象列表
}
公共接口IData:IData,其中T:BaseObject
{
Search Search;//返回
}
公共类:IData
{
搜索;
} 
公共类browstata:browstata,IData其中T:BaseObject
{
搜索;
}
公共类浏览器生成器
{
受保护的数据;
公共浏览器生成器(浏览器数据)
{
数据=数据;
}
公共空间
{
//使用提供的数据进行渲染
}
}
公共类BrowseBuilder:BrowseBuilder,其中T:BaseObject
{
受保护的新数据;
公共浏览器生成器(浏览器数据)
{
数据=数据;
}
}
我的问题是在非通用类BrowseBuilder中实现的方法DoRender,它使用非通用数据/搜索进行渲染,该渲染将返回baseObject列表,而通用版本将返回T的列表


也许我看错了,不管怎样,搜索都应该是非泛型的,操作它的基方法应该只返回baseObject列表。

这并不漂亮,但它起到了作用:您可以在基类中定义一个事件,以公开
SomeVar
中的值更改,并相应地更新派生类中的属性。反之亦然。隐式地说,这意味着
FooBar
是从
FooBar
派生而来的,这在代码中没有显示

public class Foo {
    private FooBar _someVar;
    protected FooBar SomeVar {
        get { return _someVar; }
        set {
            if (_someVar != value) {
                _someVar = value; 
                OnSomeVarUpdated();
            }
        }
    }

    protected event EventHandler SomeVarUpdated;
    private void OnSomeVarUpdated() {
        var someVarUpdated = SomeVarUpdate;
        if (someVarUpdated != null) {
            someVarUpdated(this, EventArgs.Empty);
        }
    }

    public virtual void DoSomething() {
        // Manipulate SomeVar here
        var someVar = ....;
        SomeVar = someVar;
    }
}

public class Foo<T>: Foo where T: SomeObject {
    public Foo() {
        OnSomeVarUpdated += () => {
            // Pull new value from base
            SomeVar = (FooBar<T>)base.SomeVar;
        };
    }

    private FooBar<T> _someVar;
    protected new FooBar<T> SomeVar {
        get { return _someVar; }
        set {
            if (_someVar != value) {
                _someVar = value;
                // Push new value to base
                base.SomeVar = value;
            }
        }
    }
}
公共类Foo{
私人FooBar_someVar;
受保护的FooBar SomeVar{
获取{return\u someVar;}
设置{
if(_someVar!=值){
_someVar=值;
OnSomeVarUpdated();
}
}
}
受保护的事件处理程序已更新;
OnSomeVarUpdated()上的私有void{
var someVarUpdated=SomeVarUpdate;
if(someVarUpdated!=null){
someVarUpdated(此为EventArgs.Empty);
}
}
公共虚拟空间DoSomething(){
//在这里操纵SomeVar
var someVar=。。。。;
SomeVar=SomeVar;
}
}
公共类Foo:Foo其中T:SomeObject{
公共食物({
OnSomeVarUpdated+=()=>{
//从基础中提取新值
SomeVar=(FooBar)base.SomeVar;
};
}
私人FooBar_someVar;
受保护的新FooBar SomeVar{
获取{return\u someVar;}
设置{
if(_someVar!=值){
_someVar=值;
//将新值推送到基础
base.SomeVar=值;
}
}
}
}

以下是一个使用接口的解决方案:

public interface IFooBar
{
    // methods used for modifications
}

public class FooBar : IFooBar 
{
    // implement modification methods
}

public class FooBar<T> : IFooBar where T : SomeClass
{
    // implement modification methods
}

public class Foo
{
   protected IFooBar SomeVar;

   public void DoSomething()
   {
       // Manipulate SomeVar via IFooBar interface here 
   }
}

public class Foo<T>: Foo where T: SomeObject
{

}
公共接口IFooBar
{
//用于修改的方法
}
公共类FooBar:IFooBar
{
//实施修改方法
}
公共类FooBar:IFooBar其中T:SomeClass
{
//实施修改方法
}
公开课Foo
{
受保护的IFooBar SomeVar;
公共无效剂量测定法()
{
//在这里通过IFooBar接口操作SomeVar
}
}
公共类Foo:Foo其中T:SomeObject
{
}

这看起来好像我只是在解决问题,但是如果
FooBar
FooBar
没有公共接口,您就需要为它们实现不同的修改代码。

我个人会根据上下文、情况和您的需要选择不同的方法。对于所描述的问题,没有通用的解决方案。提供更多的上下文细节将有助于提供更准确的答案

您要求的备选方案如下:

  • 将逻辑移到
    FooBar
    类。直接或通过接口。然后,您的
    Foo
    将具有
    DoSomething()
    代理,该代理将直接在实际的
    FooBar
    实例上调用实际方法

  • 如果
    FooBar
    是一个简单的get/set类,而上面没有逻辑解决方案,则会破坏这种模式。为了克服这个问题,创建另一个用于
    FooBar
    操作的类,该类将实现所需的方法

  • 反转继承。而不是
    Foo:Foo
    使其成为
    Foo:Foo
    。但是要小心