We've implemented a silverlight 2 business application communicating through WCF and I just had to blog about something I found possible in .net in general...
On the server side we have a very simple generic object used to communicate validation issues back to our Silverlight client when a web service method is called. Here's the basic interface.
public interface IValidatedResult<T>
{
T Result { get; set; }
List<string> ValidationIssues { get; set; }
}
Now if you had a method that exposed this generic result object through your web service...
public ValidatedResult<long> StringLength(string param1)
{
return new ValidatedResult<long>(param1.Length);
}
Now if you to to the silverlight project tell Visual Studio to generate a proxy for you (against the service you just created) it will give you a proxy with an object that is not generic. You end up with some autogenerated code that looks more like...
public partial class ValidatedResultOflong : object, System.ComponentModel.INotifyPropertyChanged
{
private long ResultField;
private System.Collections.ObjectModel.ObservableCollection<string> ValidationIssuesField;
[System.Runtime.Serialization.DataMemberAttribute()]
public long Result
{
get
{
return this.ResultField;
}
set
{
if ((this.ResultField.Equals(value) != true))
{
this.ResultField = value;
this.RaisePropertyChanged("Result");
}
}
}
[System.Runtime.Serialization.DataMemberAttribute()]
public System.Collections.ObjectModel.ObservableCollection<string> ValidationIssues
{
get
{
return this.ValidationIssuesField;
}
set
{
if ((object.ReferenceEquals(this.ValidationIssuesField, value) != true))
{
this.ValidationIssuesField = value;
this.RaisePropertyChanged("ValidationIssues");
}
}
}
// stripped out the INotifyPropertyChanged goo
}
Notice the non generic type ValidatedResultOflong
that was generated? This non generic object is great and all except when you want to do some generic processing on these objects. For things like error handling, validation handling... if we had to create different handling methods for all of these different objects, that could prove to be laborious...
Say I wanted to write an extension method to do some generic processing on all objects that are a ValidatedResult of T... Unfortunately there is no common signature we can key off of to write this method with the proxy code generated by V.S.
Then I thought I would try something... Can you have a partial class in one area which contains a common property, in this case each contains a "Result" and a "ValidationIssues" property and another partial class in a different location that declares it implements an interface which defines that "Result" and "ValidationIssues" property... and would that compile?
So I wrote my first test...
Here is our auto generated partial class simulated...
public partial class Foo
{
public bool Result { get; set; }
}
I then wrote a generic result of T to define the object has a Result property.
public interface IResult<T>
{
T Result { get; set; }
}
And now the specific implementation with a long Result type.
public partial class Foo : IResult<long> {}
After putting those three structures together I hit Build in VS and to my surprise (at first, but now it makes total sense) it compiled... This was great news. This meant I could create a generic processor for my wcf objects in silverlight... I'll show how on the silverlight side below...
I defined the validated result contract as follows...
public interface IResultProperty<T>
{
T Result { get; }
}
public interface IValidatedResult<T> : IResultProperty<T>
{
List<string> ValidationIssues { get; set; }
}
This meant I could quickly create partial class stubs for each of the wcf generated objects that looked like... ValidatedResultOf{object} and would define to the compiler that all these objects truly implemented the ValidationIssues and Result property.
Here's an example of the partial class for the ValidatedResultOflong
public partial class ValidatedResultOflong : IValidatedResult<long> { }
With that in place, this meant I could create some generic handling methods for all of my objects that now implement IValidatedResult<T>
...
public static bool HasValidationIssues<T>(this T validatedResult)
where T : IValidatedResult<T>
{
if (validatedResult != null &&
validatedResult.ValidationIssues != null &&
validatedResult.ValidationIssues.Count > 0)
return true;
else
return false;
}
Don't know if i've very heard anyone talk about one partial class containing some property or common method and being able to create another partial class that defines the interface contract for that... Pretty cool...
I haven't pushed it very far (bool, string, MyCustomObject, etc)