Is there an equivalent to the System.ComponentModel.IExtenderProvider geered toward WPF ?
Do I have to go toward Dependency Properties and Attached Properties to build an equivalent, or is there already something baked in the oven waiting for me ?
Thanks,
Patrick
The Attached Property is the way to go http://msdn.microsoft.com/en-us/library/ms749011.aspx
You can also use AttachedPropertyBrowsableForChildrenAttribute to tell a control to extend the newly created property to all its children (Has Grid's row property).
The WPF reader and writer for XAML have no awareness of the System.ComponentModel.Container concept used in Windows Forms. XAML deploys a comprehensive system of XamlType types, including XamlMember, XamlPropery, etc., all unified under a XamlSchemaContext, and which together represent a full-blown type system superimposed over--and largely independent of--the .NET type system (i.e., "reflection"). XAML "attached properties" are only defined by-and-within this universe and are therefore existentially confined to it.
While some of this is unrelated to System.ComponentModel really, it is indeed unfortunate that these two major architectural frameworks do not, in fact conspire, communicate, or collude to collectively correlate, conflate or co-opt the concepts they do contain in common.
The good news, however--and the reason for this tardy post, and the answer to your question--is that XamlServices does have extension points to address your scenario. Because all of those "Xaml..." type-types I mentioned above are represented by public classes that are not sealed and can be overridden. The starting point is to create your own customized XamlSchemaContext and override GetXamlType method to provide your own customized XamlType-derived objects wherever your situation requires.
XamlType is where you can intercept, modify, or inject, whatever attached property behavior you want. See the LookupAttachableMember or LookupAllAttachableMembers method overrides. A method in your XamlType implementation which might be of particular interest to override is XamlType.LookupInvoker(...), which allows you to supply a customized XamlTypeInvoker instance which, in turn, has a CreateInstance(...) override that can ultimately control any/all aspects of the instance(s) deployed to the resulting deserialized object graph.
In the extreme, XamlTypeInvoker.CreateInstance can substitute some or all of the XAML-resolved CLR types entirely, but this starts to defeat the larger purpose, since any such "replacement" CLR types--just like all CLR types instantiated by XamlServices--must always have a pre-existing CLR definition. In other words, what XAML does not do--but you could certainly add via this override!--is use reflection TypeBuilder etc., to synthesize new types or members that do not already have a CLR Type equivalent.
To be clear, this means that there's no way to get WPF to recognize any sort of putative "synthetic" customized type instance, nor data-bind to "virtual" runtime properties, via just manipulating XamlType or XamlMember alone.
Meanwhile, once you've overridden types and properties and other members to create your own derived XAML type system under your derived XamlSchemaContext, you can supply an instance of that schema to the XAML reader and writer methods in XamlServices.
You can pass your custom XAML schema context into the constructors for the standard XAML readers/writers, such as XamlXmlReader and XamlObjectWriter (for the so-called "load path" scenario; I won't discuss the "save path" here). More importantly, however, you can also override these two classes as well, and they provide a rich set of virtual methods to override. As a pseudo-code example (lifted from my working code), you can add a transform(...) method to your XamlXmlReader-derived class that provides full control of a XAML deserialized object result:
// ...in your class derived from 'XamlXmlReader'
public void transform(my_xaml_obj_writer xow)
{
while (base.Read())
{
if (xow.ShouldProvideLineInfo)
xow.SetLineInfo(LineNumber, LinePosition);
switch (NodeType)
{
case XamlNodeType.NamespaceDeclaration:
xow.WriteNamespace(base.Namespace);
break;
case XamlNodeType.StartObject:
xow.WriteStartObject(base.Type);
break;
case XamlNodeType.EndObject:
xow.inject_ctor_arg(); // <--- !! (not shown)
xow.WriteEndObject();
break;
case XamlNodeType.StartMember:
xow.inject_ctor_arg(); // <--- !! (not shown)
xow.WriteStartMember(base.Member);
break;
case XamlNodeType.EndMember:
xow.WriteEndMember();
break;
case XamlNodeType.GetObject:
xow.WriteGetObject();
break;
case XamlNodeType.Value:
xow.WriteValue(base.Value);
break;
case XamlNodeType.None:
break;
}
}
}
Using this custom reader, the process of deserializing XAML to an in-memory CLR object is something like this:
void XamlToObject(FileStream fs, my_xaml_schema_context ctx)
{
using (var xxr = new xaml_xml_reader(fs, ctx))
using (var xow = new my_obj_writer(this))
{
try
{
xxr.transform(xow);
}
catch (XamlObjectWriterException xex)
{
// ...
}
}
}
The resulting XAML "root object", the in-memory CLR object which is the whole point, will be found on the Result property of your overridden XamlObjectWriter at the end of this process. In my case, I actually snoop the result object out of the XAML node stream earlier during the transform method shown above, as soon as it is created, in order to see if it has the [UsableDuringInitialization] attribute, and accordingly enable certain concurrent uses while the deserialization is still in progress.
Finally note that XamlObjectWriterSettings and XamlXmlReaderSettings can also be overridden with your own derived classes, if you want to add additional settings. More commonly you might just need to do this in order to make additional custom data available to yourself, since with overridden methods in XamlServices you tend to sometimes find yourself deep within the bowels of a callback while seemingly having insufficient contextual information.
Related
Trying to refactor some old code full of anti-patterns, bad code, and 10 years of piling up things with almost no remorse. There are a bunch of questions, so pardon me for this conceptual mess.
It is a text editor with scripting capabilities (Python and other), custom scripting language, access to databases and much more. Maybe nothing different from what Office, LibreOffice or similar do.
1.- First, I need to keep track of all those objects, parsing the text and creating a list of what I have called "DocumentObject":
E.g.:
[*variable*] represents a variable
[<py>code</py>] represents a python script
When the "parser" finds a match in the text (based on regex patterns), it creates a DocumentObject according to its type and stores its Regex Match.
Having different DocumentObject types (variables, scripts, database calls,...), I was thinking about creating different DocumentObject classes based on those types (i.e.: DocumentObjectVariable, DocumentObjectScript, DocumentObjectData, and so on).
public class DocumentObject : IDocumentObject
{
public DocumentObjectType DocumentObjectType { get; set; } = DocumentObjectType.None;
// RegEx Match to store position and value of found 'language pattern'
public Match Match { get; set; }
public DocumentObject(DocumentObjectType documentObjectType, Match match)
{
DocumentObjectType = documentObjectType;
Match = match;
}
}
Until now I was not using interfaces, only deriving from DocumentObject base class. But now I want to know if using DI or factory method is the way to go.
For now, it is a basic:
documentObjectList.Add(new DocumentObject(DocumentObjectType.Variable, match));
So, having a required constructor parameter (at least the RegEx Match)...I need to know which is the optimal pattern or approach.
2.- Once the "tracking" (parse) part is completed, the next step is to Run the document to replace all those found DocumentObject with its different type behaviours (e.g: [*variable*] will be replaced by its actual value ([*name*] -> John))
For the sake of optimal coding, it is better to add, for example, an Execute method in the DocumentObject class or let a Service / Handler / Controller like class to handle all the process?
public Task<string> Execute()
{
// Do whatever, like getting the variable value or executing a script
// return the final string that will replace the DocumentObject Match in the text
}
I'm going to assume that you want the code to be SOLID and DRY. I'm also going to assume that when you say 're-factoring' you mean that you are creating tests that show that the code produces the same 'results' before and after the implementation changes.
The 'D' in SOLID is the "dependency inversion principle" (DIP). Dependency injection (DI) can help you implement dependency inversion (DIP) but DIP and DI are different concepts.
Because the question seems to be about design advice, I will offer the following general suggestions:
Prefer to use interfaces for polymorphism, over inheritance.
You might use a factory class that can produce different types of objects for the same interface.
Avoid having a property that represents the type. The object itself is its type. (i.e. Don't have the DocumentObjectType property.)
Avoid switch statements on the object type. (i.e. Don't have a switch on obj.DocumentObjectType.) Try to put the code from each switch block into each type of object. e.g. an IPet interface may have a Vocalize() method. You can call myPet.Vocalize() regardless of whether the instance is actually a Dog (which may 'bark') or a Cat (which may 'meow'). (Admittedly a bad example but hopefully illustrates the point.)
Prefer composition over inheritance to share common code. i.e. Instead of derived classes that share code in a base class that provides access to certain data, 'inject' a data provider class into each instance. (This is where a DI container helps. It can be the factory and cache for the providers.)
My preference is to inject dependencies via the constructor. An object should be useable if it is constructed (and the constructor should fail if the object won't be useable.)
Finally don't try to change everything all at once. It's not an all-or-nothing situation. Tackle the challenge in small steps.
Though I'm of course familiar with auto-properties, I just ran across this at work, which seems to be a distinctly different beast:
public SomeType SomeProp
{
get
{
return someField;
}
set
{
}
}
I was surprised it even compiled, and I imagine it must be a bug: the property seems to allow setting, but doing so does absolutely nothing.
Is there a use for this construct? Is it like those "Close Door" buttons in elevators that don't do anything, but make the user feel good?
Why would you expect it not to compile? The setter is just a void method with a single parameter, effectively. You can write broken methods perfectly easily without expecting the compiler to notice - and the same is true of properties.
I can't easily imagine any case where this would be deliberate, however, other than for "partial" implementations - e.g. to demonstrate language features, or if you're testing something that does set a property, but you don't care what the test sets it to. (I'd personally still usually at least record that the property had been set.)
You often see this when a result needs to be serialized in a web service or using an XML or binary serializer.
It's lazy and sloppy, but it happens often. This leaves the object with the "appearance" that the property is settable. If it's done to implement an interface and allow compilation, then the developer who did it needs to be beaten liberally about the head and shoulders with a blunt object, as he just broke the interface. If there is a valid reason that it can't be implemented, then the developer needs to kick it back up to the architect for review. You don't just leave empty stubbed methods behind when implementing an interface. If you don't have a technique defined for implementation at the moment, then at least throw a new NotImplementedException so the unit tests will catch it.
As far as serialization: ReadOnly properties don't get included in regular serialization, and that can leave the property unavailable to a web service client. (ref: Read-Only Properties Cannot Be Exposed by XML Web Services.) This is one of the reasons we should all be moving to WCF and DataContracts. If you accept this class as an input type for a method through WCF, then again retrieve the blunt object.
This doesn't seem useful by itself but consider an interface that required classes to have a SomeProp and you need to implement this interface in your class but have SomeProp only readable and not writeable.
public interface IQuestion
{
public int AnwserToLife { get; set; } //leave out 'set' for read-only
}
public class HitchHiker : IQuestion
{
public int AnwserToLife
{
get
{
return 42;
}
set
{
//never changes
}
}
}
There are a few use cases, where this would be a necessary workaround, some of which I have already encountered "in the wild".
E.g.: The property is a remains from old times, no longer of use, but some other part of the app has never been updated (Source lost? Third party?) and insists on setting the property. I have seen that in old code, that required plugins to set a isDirty property after updating some dataset, when the implementation changed to observe the dataset on itself, the isDirty property became useless, but couldn't be put away, because other code still wants to set it.
I would recommend avoiding this kind of programming. It compiles, because there is no reason it shouldn't, but if the interface requires you to implement a setter method, then there are two options:
Either the setter is redundant and the property should be made read-only, or
There exists a part of your code which will set this value and falsely assume that it worked.
I have a control circuit which has multiple settings and may have any number of sensors attached to it (each with it's own set of settings). These sensors may only be used with the control circuit. I thought of using nested classes like so:
public class ControlCircuitLib
{
// Fields.
private Settings controllerSettings;
private List<Sensor> attachedSensors;
// Properties.
public Settings ControllerSettings
{ get { return this.controllerSettings; } }
public List<Sensor> AttachedSensors
{ get { return this.attachedSensors; } }
// Constructors, methods, etc.
...
// Nested classes.
public class Settings
{
// Fields.
private ControlCircuitLib controllerCircuit;
private SerialPort controllerSerialPort;
private int activeOutputs;
... (many, many more settings)
// Properties.
public int ActiveOutputs
{ get { return this.activeOutputs; } }
... (the other Get properties for the settings)
// Methods.
... (method to set the circuit properties though serial port)
}
public class Sensor
{
// Enumerations.
public enum MeasurementTypes { Displacement, Velocity, Acceleration };
// Fields.
private ControlCircuitLib controllerCircuit;
private string sensorName;
private MeasurementTypes measurementType;
private double requiredInputVoltage;
... (many, many more settings)
// Properties.
public string SensorName {...}
... (Get properties)
// Methods.
... (methods to set the sensor settings while attached to the control circuit)
}
}
I have read that public nested classes are a "no-no" but that there are exceptions. Is this structure OK or is there a better option?
Thanks!
EDIT
Below is a crude hierarchy of the control circuit for which I am trying to write a library class for; I used code formatting to prevent text-wrap.
Control Circuit (com. via serial port) -> Attached Sensors (up to 10) -> Sensor Settings (approx. 10 settings per sensor)
Basic Controller Settings (approx. 20 settings)
Output Settings (approx. 30 settings)
Common Settings (approx. 30 settings)
Environment Settings (approx. 10 settings)
All of the settings are set through the controller but I would like an organized library instead of just cramming all ~100 methods, properties, and settings under one Controller class. It would be HUGELY appreciated if someone could offer a short example outlining the structure they would use. Thanks!
The contents of a class should be the implementation details of that class. Are the nested classes implementation details of the outer class, or are you merely using the outer class as a convenient name scoping and discovery mechanism?
If the former, then you shouldn't be making the private implementation details publically available. Make them private if they are implementation details of the class.
If the latter, then you should be using namespaces, not outer classes, as your scoping and discovery mechanism.
Either way, public nested classes are a bad code smell. I'd want to have a very good reason to expose a nested class.
I don't have too much problem with public nested classes (I'm not a fan of dogmatic rules, in general) but have you considered putting all of these types in their own namespace instead? That's the more common way of grouping classes together.
EDIT: Just to clarify, I would very rarely use public nested classes, and I probably wouldn't use them here, but I wouldn't completely balk at them either. There are plenty of examples of public nested types in the framework (e.g. List<T>.Enumerator) - no doubt in each case the designers considered the "smell" of using a nested class, and considered it to be less of a smell than promoting the type to be a top-level one, or creating a new namespace for the types involved.
From your comment to Eric's answer:
These sensors can ONLY be used with a specific circuit
This kind of relationship is commonly known as a dependency. The Sensor constructor should take a ControlCircuit as a parameter. Nested classes do not convey this relationship.
and you can't get/set any sensor settings without going through the controller circuit;
I think that means that all Sensor properties will delegate to (call) or somehow inform (fire an event on) the ControlCircuit when they're used. Or, you'd have some kind of internal interface to the sensor that only the control circuit uses, making Sensor an opaque class to the outside world. If that's the case, Sensor is just an implementation detail and could be nested private or internal (there's also no need to "save" a sensor instance if you can't do anything with it).
Also, I don't even want to expose a Sensor constructor (the controller will have a method for this)
The fact that the Sensor constructor now takes a control circuit is enough of a hint as to what depends on what that you could leave the constructor public. You can also make it internal.
A general comment that I have is that this design is very coupled. Maybe if you had some interfaces between control circuit, sensor and settings, it would be easier to understand each component independently, and the design would be more testable. I always find beneficial to make the roles that each component plays explicit. That is, if they're not just implementation details.
I would say the better option is moving those nested classes out of the class they're in and have them stand on their own. Unless I'm missing something you appear only to have them in the main class in order for some sort of scoping concept, but really, that's what namespaces are for.
I generally disagree with Eric on this.
The thing I usually consider is: how often should the end user use the type name ControlCircuitLib.Sensor. If it's "almost never, but the type needs to be public so that doing something is possible", then go for inner types. For anything else, use a separate type.
For example,
public class Frobber {
public readonly FrobType Standard = ...;
public readonly FrobType Advanced = ...;
public void Frob(FrobType type) { ... }
public class FrobType { ... }
}
In this example, the FrobType only acts as an opaque 'thing'. Only Frobber needs to know what it actually is, although it needs to be possible to pass it around outside that class. However, this sort of example is quite rare; more often than not, you should prefer to avoid nested public classes.
One of the most important things when designing a library is to keep it simple. So use whichever way makes the library and the using code simpler.
I like nested classes in cases like this because it shows the relationship. If you do not want users of the outer class to be able to create items of the inner class separately from the outer class, you can always hide the constructors and use factory methods in the outer class to create elements of the inner class. I use this structure a lot.
This structure seems completely reasonable to me. I wasn't aware until today that Microsoft has advised against doing this, but I'm still not aware why they've advised as such.
I've used this structure in a situation where the nested class only exists to support the containing class (i.e. it's part of its implementation), but other classes need to be able to see it in order to interact with the containing class (i.e. it's part of the class's API).
That being said, Eric generally knows what he's talking about, so out of respect for his knowledge and for the time being, I've converted those classes to use namespaces instead.
Currently, I'm not liking the results. I have a class named BasicColumn, which exists only to represent a column in a class called Grid. Previously, that class was always addressed as Grid.BasicColumn, which was great. That's exactly how I want it to be referred to. Now, with the Grid and the BasicColumn both in the Grids namespace, it's just referred to as BasicColumn with a 'using Grids' at the top of the file. There's nothing to indicate its special relationship with Grid, unless I want to type out the entire namespace (which has a few prefixes before Grid I've left out for simplicity).
If anyone can point out an actual reason why using public nested classes is somehow counterproductive or suboptimal, other than the irrelevant fact that Microsoft doesn't intend for them to be used that way, then I'd love to hear it.
While I feel Eric's answer is correct, it is important to realize it doesn't really fully address what your situation is.
Your case sounds very similar to one I frequently find myself in where you have a class which is really implementation details of another class, however, some details or functionality of that sub-component naturally lend themselves towards being exposed directly for some minor aspects that are not governed by the parent.
In these cases, what you can do is use interfaces. The nested classes need not be public as they really are internal details of the class they are nested within, but a subset of functionality (an interface) needs to be made publicly available and can be implemented by the class.
This allows for construction of the internal structures to be controlled by the class they are nested within while still allowing direct access to the type from a namespace for external references. (The caller will use SomeNamespace.IChildApi as the name rather than SomeNamespace.NestingClass.NestedClass.SecondNestedClass.ThirdNestedClass, etc.)
Okay Stackers, I've spent a good couple of hours on this question, and I want to know if anybody has a definitive answer.
For all the research I've done, I can't find ANY difference between .Register and .RegisterAttached in Silverlight. Now, before you jump the gun and tell me that .RegisterAttached is used for attaching a DP to another class, try implementing an Attached Dependency Property using DependencyProperty.Register(). I have found not a single difference, and so I am at a loss as to what the difference is.
Furthermore, in my specific case, I'm attempting to extend the functionality of the Grid class, and want to give it some extra properties. As such, I've tried listing passing both typeof(Grid) and typeof(FluidLayoutManager) (the implementing class) as the ownerType parameter and it also seems to make very little difference... (I believe it does make a difference when I pass two custom classes from the same namespace. However when passing a Microsoft defined class vs. a custom class, I always have it showing up in the XAML as a DP of the custom class.)
Any clarification on this topic would be much appreciated, as I'm sitting here scratching my head, and wondering if there is any difference at all, or if Microsoft is just screwing with me once again.
Given the discussions flowing in comments I will try to do this one in plain English:
The main difference between Attached Dependency Properties and Dependency Properties (and therefore between .Register and .RegisterAttached) is that RegisterAttached allows the value to be assigned to any dependency object whereas Register only allows it to be attached to the class passed as the ownerType parameter.
As Haris Hasan mentions (deep in the comment thread), your example is using the only type allowed (i.e. CustomControl) and does not show you that the Attached version can be assigned to ANY dependency object.
e.g. you can do this with your Attached Dependency Property (but not a plain DP):
<Grid local:AttacherClass.ADP1="1" x:Name="LayoutRoot" Background="White">
</Grid>
The best reference for ADPs I can find is this one: http://msdn.microsoft.com/en-us/library/ms749011.aspx
We used ADPs as the basis of a localisation system, so that translations could be parasited onto objects during load rather than using horrendously long bindings. Couldn't do that with DPs
Update:
I would also like to clarify that the parent limitation applies to XAML based use of the attribute. From code the parent limitation apparently does not apply.
It is wrong to believe that "RegisterAttached allows the value to be assigned to any dependency object whereas Register only allows it to be attached to the class passed as the ownerType parameter". Here is a perfectly working example of an attached property registered with Register:
class FooPropertyDeclaringType
{
public static readonly DependencyProperty FooProperty =
DependencyProperty.Register("Foo", typeof(int), typeof(FooPropertyDeclaringType));
}
class SomeUnrelatedType : DependencyObject { }
class Program
{
static void Main()
{
var obj = new SomeUnrelatedType();
obj.SetValue(FooPropertyDeclaringType.FooProperty, 10);
Debug.Assert(10 == (int)obj.GetValue(FooPropertyDeclaringType.FooProperty));
}
}
Reflector shows that the only difference between Register and RegisterAttached is that the Register throws out much of the supplied metadata and only preserves it for the instances of registering class (via OverrideMetadata). It means that attributes such as Inherits and various update notifications usually specified in the metadata do not work on properties registered with Register and attached to objects of other types (other than the registering type). So Register is actually a stripped down version of RegisterAttached. It was probably made this way for performance reasons.
In the example linked by Haris Hasan in the comments to his answer, if you change RegisterAttached to Register, the buttons stop moving (because the property no longer provides AffectsParentArrange metadata for Button type) but they are nevertheless redrawn in their new locations when you resize the window. But if you add the same metadata to the Button type after a call to InitializeComponent():
RadialPanel.AngleProperty.OverrideMetadata(
typeof(Button),
new FrameworkPropertyMetadata(
0.0, FrameworkPropertyMetadataOptions.AffectsParentArrange));
then everything works again as if RegisterAttached was called.
They might not be much different as far as implementation is concerned but they are difference in actions i.e. they are different in what they do and are used for.
Simple Register is used for simple dependency properties which you usually are used for bindings and validations so they are normal CLR properties with some additional magic which helps in WPF
RegisterAttached is normally used where you want to expose a property that can be accessed and set in the child class like DockPanel where children of control tells parent where they want to be placed using Dock.Left or Dock.Right. So they are kind of special dependency properties which can be accessed in the child controls (which is not the case with simple Register properties) and they(in case of DockPanel) helps parent control in displaying children
In short one cay say Register is used registering dependency properties which are used in same class while RegisterAttached is used for registering special dependency properties called attached properties and they are used and accessed by classes other than one which defined it
This is a good explanation of Attached Properties and what cannot be achieved through simple DP
If you register with RegisterAttached, it becomes global as a property in the store of any DependencyObject, i.e. you could SetValue on any Dependency Object
If you use Register when Get/Setvalue are called there will be a check that the call is prom an object that is castable to the registering type.
An Example of a property that behaves like RegisterAttached is Grid.Row and Grid.Column.
So exactly what is 'ownerType' used for in RegisterAttached? This issue has been nagging at me for a few years, so I finally took a closer look at 4.6.1 code in WindowsBase.
For any DependencyProperty, attached or otherwise, what it eventually comes down to is what type of PropertyDescriptor WPF obtains for late-bound XAML access, and this isn't determined until the first time (on a per type/property pairing basis) such access is attempted. This deferral is necessary because PropertyDescriptor encapsulates a property bound to a specific type, whereas the point of attached properties is to avoid exactly this.
By the time XAML access occurs, the Register(...) versus RegisterAttached(...) distinction has been lost to the mists of (run)time. As others have noted on this page, 'DependencyProperty' itself doesn't encode a distinction between an attached vs. non- variety. Every DP is assumed to be eligible for either usage, subject only to what can be figured out at runtime.
For example, the .NET code below seems to rely on not finding a matching instance property on the 'tOwner' type as the first requirement for allowing attached access. To confirm this diagnosis, it then checks whether 'tOwner' exposes one of the static access methods. This is a vague check insofar as it doesn't verify the method signatures. Those signatures only matter for XAML access; all actual runtime targets for the attached property must be DependencyObjects, which WPF accesses through DependencyObject.GetValue/SetValue whenever possible. (The VS Designer reportedly does use the static accessors, and your XAML won't compile without them)
The relevant .NET code is the static function DependencyPropertyDescriptor.FromProperty, shown here with my own comments (summary below):
internal static DependencyPropertyDescriptor FromProperty(DependencyProperty dp, Type tOwner, Type tTarget, bool _)
{
/// 1. 'tOwner' must define a true CLR property, as obtained via reflection,
/// in order to obtain a normal (i.e. non-attached) DependencyProperty
if (tOwner.GetProperty(dp.Name) != null)
{
DependencyPropertyDescriptor dpd;
var dict = descriptor_cache;
lock (dict)
if (dict.TryGetValue(dp, out dpd))
return dpd;
dpd = new DependencyPropertyDescriptor(null, dp.Name, tTarget, dp, false);
lock (dict)
dict[dp] = dpd;
/// 2. Exiting here means that, if instance properties are defined on tOwner,
/// you will *never* get the attached property descriptor. Furthermore,
/// static Get/Set accessors, if any, will be ignored in favor of those instance
/// accessors, even when calling 'RegisterAttached'
return dpd;
}
/// 3. To obtain an attached DependencyProperty, 'tOwner' must define a public,
/// static 'get' or 'set' accessor (or both).
if ((tOwner.GetMethod("Get" + dp.Name) == null) && (tOwner.GetMethod("Set" + dp.Name) == null))
return null;
/// 4. If we are able to get a descriptor for the attached property, it is a
/// DependencyObjectPropertyDescriptor. This type and DependencyPropertyDescriptor
/// both derive directly from ComponentModel.PropertyDescriptor so they share
/// no 'is-a' relation.
var dopd = DependencyObjectProvider.GetAttachedPropertyDescriptor(dp, tTarget);
/// 5. Note: If the this line returns null, FromProperty isn't called below (new C# syntax)
/// 6. FromProperty() uses the distinction between descriptor types mentioned in (4.)
/// to configure 'IsAttached' on the returned DependencyProperty, so success here is
/// the only way attached property operations can succeed.
return dopd?.FromProperty(dopd);
}
Summary: When calling RegisterAttached to create an attached DependencyProperty, the only thing 'ownerType' is used for is to identify a type which defines appropriate static Get/Set accessors. At least one of those accessors must exist on 'ownerType' or XAML attached access will not compile or silently fail. Although RegisterAttached does not fail in this case, and instead successfully returns a defunct DP. For DPs intended for attached use only, 'tOwner' doesn't have to derive from DependencyObject. You can use any regular .NET class, static or non-static, and in fact can even be a struct!
I'm writing a .NET web application in which administrators can customize the various data entry forms presented to their users. There are about half a dozen different field types that admins can create and customize (i.e. text, numeric, dropdown, file upload). All fields share a set of base attributes/behaviors (is the field required? Will it have a default field value?). There are also a series of field specific attributes/behaviors (i.e dropdown has a data source attribute, but text field does not). I'm leaving out many other characteristics of the problem domain for simplicity's sake.
The class hierarchy is straightforward: An abstract superclass that encapsulates common behaviors/attributes and about half a dozen concrete subclasses that deal with field specific stuff.
Each field type is rendered (i.e. mapped to) as a specific type of .NET server control, all of which derive from System.Web.UI.Control.
I created the following code to map values between the field domain objects and their corresponding UI control:
public static void Bind(Control control, IList<DocumentFieldBase> fieldBaseList)
foreach (DocumentFieldBase fieldBase in fields){
if (typeof (DocumentFieldText).IsInstanceOfType(fieldBase)){
TextBox textbox = (TextBox) control;
textbox.Text = (fieldBase as DocumentFieldText).GetValue();
}
if (typeof (DocumentFieldDropDown).IsInstanceOfType(fieldBase)){
DropDown dropDown= (DropDown) control;
dropDown.Text = (fieldBase as DocumentFieldSelectOne).GetValue().Text;
dropDown.DataSource= (fieldBase as DocumentFieldSelectOne).DataSource;
dropDown.Id= (fieldBase as DocumentFieldSelectOne).GetValue().Id;
}
//more if statements left out for brevity
}
}
I want to ditch those ungodly if statements that perform type checking. The approach I was shooting for was to create a method overload for each combination of field/control using subclass typing. For example:
public static void Bind(TextBox control, DocumentFieldText fieldText){
//some implementation code
}
public static void Bind(DropDown control, DocumentFieldDropDown fieldDropDown){
//some implementation code
}
I was hoping that I could then rely on .NET to call the appropriate overload at runtime using the specific subclass being used: For example:
foreach (DocumentFieldBase field in fields){
Control control = FindControl(field.Identifier);
Bind(control, field)
}
Unfortunately, the compiler chokes when I try this:
Argument '1': cannot convert from 'System.Web.UI.Control' to 'TextBox'.
If I have to cast the first argument to TextBox, I'm back to performing type checking myself and defeats the whole purpose of this exercise.
Is what I'm trying to achieve a) possible and b) a good idea?
Prior to C# 4, all overloading is done at compile time. You have to use double dispatch or the visitor pattern to effectively overload at execution time, and that gets messy quickly.
In C# 4, you could declare a variable as dynamic and let it all get sorted out at execution time:
foreach (DocumentFieldBase field in fields){
dynamic control = FindControl(field.Identifier);
Bind(control, field)
}
Obviously that's not much help at the moment though (unless you're using VS2010b1).
One option is to use a map from Type to Action<object> but then you get inheritance issues... (you'd potentially have to keep working up the type hierarchy from the concrete type up to object until you found an entry in the map). You'd also still need to cast to the right type within the action :(
The "dispatch" tag on this question is quite appropriate: what you want is called "multiple dispatch". C# (like most mainstream languages) only supports "single dispatch", where the method to be executed is selected solely on the (runtime) type of the object you call the method on, not on the (runtime) type of its arguments.
The visitor pattern can often be used to work around this. The idea is that you give DocumentFieldBase a method (that you override in concrete subclasses) which calls a method on Control (also overridden in concrete subclasses) that does the actual work.
Unfortunately, the source code of the Control class is probably not under your control*... so you'll have to resort to an even more hackish solution. The accepted answer to this question provides one that uses reflection.
*Extension methods are just syntactic sugar for static methods, and are thus resolved at compile time and of no use in this scenario.
Couldn't you have an abstract, non-static Bind() method in DocumentFieldBase, then do the downcasting inside each concrete class's implementation of it? Each DocumentFieldBase class knows what type of Control it's getting, doesn't it?