我有几个共享一些常见属性的UserControl。例如:
private List<MyObject> Sample
{
get
{
return Session["MyObject"] as List<MyObject>;
}
set
{
Session["MyObject"] = value;
}
}
我想将此分享给我项目中的所有用户控件。 (当然,不是解决方案中的其他项目)。我要做的是创建一个单独的类并从该类继承。类似的东西:
public class SampleBase : Web.UI.UserControl
{
protected List<MyObject> Sample
{
get
{
return Session["MyObject"] as List<MyObject>;
}
set
{
Session["MyObject"] = value;
}
}
}
然后我的控件可以通过从该类派生来继承这些值:
partial class myControl : SampleBase
我遇到的一个问题是,如果控件已经存在继承的东西,我无法从base派生:
partial class myControl : SomethingELSE
否则它工作正常,但我不确定这是否是一个好方法,我正在寻找建议。
答案 0 :(得分:10)
如果我的理解是正确的,您只想摆脱用户控件的继承层次结构
另一种方法是使用Extension Methods
例如:
public interface IMyUserControlMark { }
public static class MyUserClassExtensions
{
public static List<object> GetSampleData(this IMyUserControlMark myUserControl)
{
if (HttpContext.Current.Session["MyObject"] == null)
{
return Enumerable.Empty<object>().ToList();
}
return HttpContext.Current.Session["MyObject"] as List<object>;
}
public static void SetSampleData(this IMyUserControlMark myUserControl, List<object> myObject)
{
HttpContext.Current.Session["MyObject"] = myObject;
}
}
public partial class Content1 : System.Web.UI.UserControl, IMyUserControlMark
{
...
}
public partial class Content2 : System.Web.UI.UserControl, IMyUserControlMark
{
....
}
现在,您可以在UserControl中或从后面的ASPX代码中调用您的扩展方法,如下所示:
var myObject = this.GetSampleData();
this.SetSampleData(myObject);
var myObject = this.uc1.GetSampleData();
this.uc1.SetSampleData(myObject);
答案 1 :(得分:2)
这是一个经典的例子,你需要“赞成合成而不是继承”。
您不是从类中继承继承,而是拥有对该类实例的引用。然后,您提供简单的传递代码来访问类的方法/属性。
所以,举个例子:
public class SomeBehavior
{
public List<MyObject> Sample
{
get { return Session["MyObject"] as List<MyObject>; }
set { Session["MyObject"] = value; }
}
}
public class MyControl : UserControl
{
private SomeBehavior _someBehavior;
public MyControl()
{
_someBehavior = new SomeBehavior();
}
public List<MyObject> Sample
{
get { return _someBehavior.Sample; }
set { _someBehavior.Sample = value; }
}
}
另一种选择是允许直接访问行为类:
public class MyControl : UserControl
{
public SomeBehavior SomeBehavior { get; private set; }
public MyControl()
{
SomeBehavior = new SomeBehavior();
}
}
这样做的好处是您不必编写传递代码。缺点是它违反了Law of Demeter,它表示你应该“只与你的直接朋友交谈”。如果您这样做,其他使用MyControl
的类需要了解SomeBehavior
。遵循Demeter法则可以提高代码的可维护性和适应性,但需要花费大量的传递代码。
答案 2 :(得分:0)
除了以前的解决方案,也许是时候应用一些MVC / MVP模式了? 对于Web表单,有一个很棒的框架,名为WebFormsMVP:link 在库中有一种称为Cross Presenter Messaging的机制,您可以使用发布/订阅模式在控件之间共享数据。 有关更好的说明,请查看here和here
我建议给图书馆一个机会:)
答案 3 :(得分:0)
在C#中,您只能从一个类继承并实现多个接口。
这是允许的:
partial class myControl : SampleBase
partial class myControl : SampleBase, Interface1
partial class myControl : SampleBase, Interface1, Interface2, Interface3
这是不允许的:
partial class myControl : SomethingELSE, SampleBase
如果符合您的设计,请尝试从SomethingELSE
继承SampleBase
。如果没有,那么我建议将SampleBase
封装为需要它的每个控件的属性,因为它也建议@DanM。