I have a set of custom ASP.NET server controls, most of which derive from CompositeControl. I want to implement a uniform look for "required" fields across all control types by wrapping each control in a specific piece of HTML/CSS markup. For example:
<div class="requiredInputContainer">
...custom control markup...
</div>
I'd love to abstract this behavior in such a way as to avoid having to do something ugly like this in every custom control, present and future:
public class MyServerControl : TextBox, IRequirableField {
public IRequirableField.IsRequired {get;set;}
protected override void Render(HtmlTextWriter writer){
RequiredFieldHelper.RenderBeginTag(this, writer)
//render custom control markup
RequiredFieldHelper.RenderEndTag(this, writer)
}
}
public static class RequiredFieldHelper{
public static void RenderBeginTag(IRequirableField field, HtmlTextWriter writer){
//check field.IsRequired, render based on its values
}
public static void RenderEndTag(IRequirableField field, HtmlTextWriter writer){
//check field.IsRequired , render based on its values
}
}
If I was deriving all of my custom controls from the same base class, I coul开发者_运维知识库d conceivably use Template Method to enforce the before/after behavior;but I have several base classes and I'd rather not end up with really a convoluted class hierarchy anyway.
It feels like I should be able to design something more elegant (i.e. adheres to DRY and OCP) by leveraging the functional aspects of C#, but I'm drawing a blank.
You have an optional behavior you want to add to some objects and not others. That means you have a Proxy pattern in your problem. Create a control that is a container for other controls and does your required stuff before and after rendering any of its children.
You are right to not want to inherit to specialize. Inherit to create abstractions and variations. Delegate to specialize.
EDIT
/// <summary>
/// Create one of these panels for each required control
/// then place the required control into it
/// </summary>
public class ContainerForRequiredControls : Panel
{
protected override void Render(HtmlTextWriter writer)
{
writer.Write("<!-- header -->");
RenderChildren(writer);
writer.Write("<!-- footer -->");
}
}
精彩评论