我不确定我所做的事情是完全无效还是仅仅是糟糕的练习,但我有一个课程,让我们称之为Bar
,这是一个父类的字段,让&# 39; s调用Foo
,Bar
方法之一要求我传递父Foo
的实例作为参数。这似乎是一个糟糕而混乱的想法,但我无法想到一个更好的方法。 Foo
有效地存储了一些List<Bar>
,Bar
,ConcurrentDictionary<string,Bar>
或类似内容,用于允许我构建所有Bar
个实例,而无需重复数据。
代码的原理是这样的:
public class Foo
{
public List<Bar1> bar1List {get;set;}
public List<Bar2> bar2List {get;set;}
}
public abstract class Bar
{
//EDITED TO IMPROVE EXAMPLE
public int Value {get;set;}
public void DoSomething(Foo parentFoo)
{
}
}
public class Bar1 : Bar
{
public override void DoSomething(Foo parentFoo)
{
//EDITED TO GIVE AN EXAMPLE OF DoSomething()
this.Value = this.Value + parentFoo.bar2List[0].Value:
}
}
public class Bar2 : Bar
{
public override void DoSomething(Foo parentFoo)
{
//some other code
}
}
Foo foo = new Foo()
//populate foo somehow
foo.bar1List[0].DoSomething(foo);
//this is what looks very odd to me and feels kind of like a circular reference. The code will never be circular in that if I want to change bar1List within DoSomething() I will do it by "this", not foo.bar1List.
我考虑过将每个List<BarX>
(其中X是一个数字)作为BarX
的静态字段,但这不起作用,因为所有内容都是多线程的,我想要{{1}的多个实例1}};我考虑过使用标准方法访问父对象,但是如果我有一个List<BarX>
的父母,我就不知道如何弄乱它。有什么想法/提示吗?我不想将List<BarX>
方法移出DoSomething
。
编辑实际问题说明:
如前所述,Bar
充当所有各种Foo
实例的存储库;所有Bar
个实例都是交织在一起的,因此Bar
可能包含Bar1
。 List<Bar>
的一个家族,例如Bar
被规定为程序输入;然后使用配置文件和逻辑的wholo加载,从此List创建剩余的List<Bar1>
列表等等。总共有9种BarX
种口味,以非线性方式排列,例如我的第一个Bar
实例可能需要一个Bar1
实例,而后者又需要另一个Bar7
实例(初始Bar1
中没有该实例),依此类推。每个List<Bar1>
风格都有一个BarX
方法,取代Generate()
来确定如何构建它。这种安排非常适合线程,因此需要一个Concurrent来保存所有这些实例,其中基本思想是IfExists,返回它并分配给field / List / whatever;否则建立它并将其添加到DoSomething()
。
答案 0 :(得分:3)
实现此类目标的方法之一是为ObservableCollection
类实现Foo
以监听列表中的更改,并在添加/删除项目时添加子项目的父项。
像这样,您的方法不必引用父级,但可以通过类型为Parent
的属性Foo
访问它。
由于他们都会在Foo
实例上引用Foo
的同一个实例,因此您不会重复数据。
作为此类实现的一个示例,您可以这样做
首先定义一个可以轻松访问Parent属性的接口
public interface IChild<T>
{
T Parent { get; }
}
我们可以对Bar的DoSomething方法做同样的事情
public interface IBar
{
void DoSomething();
}
并在Abstract的Bar中实现两个接口,留下DoSomething方法摘要
public abstract class Bar : IChild<Foo>, IBar
{
private Foo parent;
public Foo Parent
{
get
{
return parent;
}
set
{
parent = value;
}
}
public abstract void DoSomething();
}
并实现Bar的2个版本,例如:
public class Bar1 : Bar
{
public override void DoSomething()
{
if (this.Parent == null)
{
throw new ArgumentException("Parent cannot be null");
}
// code against parent
Console.WriteLine("Bar 1 doing something");
}
}
public class Bar2 : Bar
{
public override void DoSomething()
{
if (this.Parent == null)
{
throw new ArgumentException("Parent cannot be null");
}
// code against parent
Console.WriteLine("Bar 2 doing something");
}
}
然后,您需要对Foo
类进行一些更改,将其自身注册到集合(Bar1Collection,Bar2Collection),并提供一种方法来监听集合中的更改。它还实现了IDisposable
接口,以便我们可以在不再需要Foo类时从CollectionChanged事件中取消注册
public class Foo : IDisposable
{
private readonly IList<Bar> bar1Collection = new ObservableCollection<Bar>();
public IList<Bar> Bar1Collection
{
get
{
return bar1Collection;
}
}
private readonly IList<Bar> bar2Collection = new ObservableCollection<Bar>();
public IList<Bar> Bar2Collection
{
get
{
return bar2Collection;
}
}
protected void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.OldItems != null)
{
foreach (var item in e.OldItems)
{
if (item is Bar)
{
var bar = item as Bar;
bar.Parent = null;
}
}
}
if (e.NewItems != null)
{
foreach (var item in e.NewItems)
{
if (item is Bar)
{
var bar = item as Bar;
bar.Parent = this;
}
}
}
}
protected void RegisterCollection(INotifyCollectionChanged collection)
{
if (collection == null)
{
return;
}
collection.CollectionChanged += OnCollectionChanged;
}
protected void UnregisterCollection(INotifyCollectionChanged collection)
{
if (collection == null)
{
return;
}
collection.CollectionChanged -= OnCollectionChanged;
}
public Foo()
{
RegisterCollection(Bar1Collection as INotifyCollectionChanged);
RegisterCollection(Bar2Collection as INotifyCollectionChanged);
}
private bool isDisposed = false;
protected virtual void Dispose(bool disposing)
{
if (!disposing || isDisposed)
{
return;
}
isDisposed = true;
UnregisterCollection(Bar1Collection as INotifyCollectionChanged);
UnregisterCollection(Bar2Collection as INotifyCollectionChanged);
}
public void Dispose()
{
Dispose(true);
}
}
作为一种测试方法,该控制台程序可以针对它运行
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics;
namespace BarFoo
{
class Program
{
static void Main(string[] args)
{
Foo foo1 = new Foo();
Bar bar1 = new Bar1();
Bar bar2 = new Bar2();
foo1.Bar1Collection.Add(bar1);
foo1.Bar2Collection.Add(bar2);
Debug.Assert(bar1.Parent != null);
Debug.Assert(bar2.Parent != null);
bar1.DoSomething();
bar2.DoSomething();
Console.WriteLine("Done");
Console.ReadLine();
foo1.Dispose();
}
}
}