For the purposes of this question, a 'constant reference' is a reference to an object from which you cannot call methods that modify the object or modify it's properties.
I want something like this:
Const<User> user = provider.GetUser(); // Gets a constant reference to an "User" object
var name = user.GetName(); // Ok. Doesn't modify the object
user.SetName("New value"); // <- Error. Shouldn't be able to modify the object
Ideally, I would mark with a custom attribute (e.g. [Constant]) every method of a class that doesn't modify the instance, and only those methods can be called from the constant reference. Calls to other methods would result in an error, if possible, during compile time.
The idea is I can return a read-only reference to and be sure that it will not be modified by the client.
The technique you're referring to is called "const-correctness" which is a language feature of C++ and Swift, but not C#, unfortunately - however you're onto something by using a custom attribute because that way you can enforce it via a Roslyn extension - but that's a rabbit-hole.
Alternatively, there's a much simpler solution using interfaces: because C# (and I think the CLR too) does not support const-correctness (the closest we have is the readonly field modifier) the .NET base-class-library designers added "read-only interfaces" to common mutable types to allow a object (wheather mutable or immutable) to expose its functionality via an interface that only exposes immutable operations. Some examples include IReadOnlyList<T>, IReadOnlyCollection<T>, IReadOnlyDictionary<T> - while these are all enumerable types the technique is good for singular objects too.
This design has the advantage of working in any language that supports interfaces but not const-correctness.
For each type (class, struct, etc) in your project that needs to expose data without risk of being changed - or any immutable operations then create an immutable interface.
Modify your consuming code to use these interfaces instead of the concrete type.
Like so:
Supposing we have a mutable class User and a consuming service:
public class User
{
public String UserName { get; set; }
public Byte[] PasswordHash { get; set; }
public Byte[] PasswordSalt { get; set; }
public Boolean ValidatePassword(String inputPassword)
{
Hash[] inputHash = Crypto.GetHash( inputPassword, this.PasswordSalt );
return Crypto.CompareHashes( this.PasswordHash, inputHash );
}
public void ResetSalt()
{
this.PasswordSalt = Crypto.GetRandomBytes( 16 );
}
}
public static void DoReadOnlyStuffWithUser( User user )
{
...
}
public static void WriteStuffToUser( User user )
{
...
}
Then make an immutable interface:
public interface IReadOnlyUser
{
// Note that the interfaces' properties lack setters.
String UserName { get; }
IReadOnlyList<Byte> PasswordHash { get; }
IReadOnlyList<Byte> PasswordSalt { get; }
// ValidatePassword does not mutate state so it's exposed
Boolean ValidatePassword(String inputPassword);
// But ResetSalt is not exposed because it mutates instance state
}
Then modify your User class and consumers:
public class User : IReadOnlyUser
{
// (same as before, except need to expose IReadOnlyList<Byte> versions of array properties:
IReadOnlyList<Byte> IReadOnlyUser.PasswordHash => this.PasswordHash;
IReadOnlyList<Byte> IReadOnlyUser.PasswordSalt => this.PasswordSalt;
}
public static void DoReadOnlyStuffWithUser( IReadOnlyUser user )
{
...
}
// This method still uses `User` instead of `IReadOnlyUser` because it mutates the instance.
public static void WriteStuffToUser( User user )
{
...
}
So, these are the first two ideas I initially had, but don't quite solve the problem.
Using Dynamic Objects:
The first idea I had was creating a Dynamic Object that would intercept all member invokations and throw an error if the method being called isn't marked with a [Constant] custom attribute. This approach is problematic because a) We don't have the support of the compiler to check for errors in the code (i.e. method name typos) when dealing with dynamic objects, which might lead to a lot of runtime errors; and b) I intend to use this a lot, and searching for method names by name every time a method is called might have considerable performance impact.
Using RealProxy:
My second idea was using a RealProxy to wrap the real object and validate the methods being called, but this only works with objects that inherit from MarshalByRefObject.
Related
I've searched through this website for anything tagged c# static interface and found that the topic rarely comes up. Examples from other websites have been similarly unsatisfactory and I've yet to come up with anything myself. I've therefore found it difficult to think of a use case for interfaces that include static fields.
Is there any design pattern, or any other idiom, that recommends the usage of a static field inside of an interface?
Traditionally interfaces are just contracts and do not contain executable code or state information but only contain abstract instance members that must be implemented by a class or a struct. Two features introduced in C# 8.0 and C# 11 add static members to interfaces. Only the first one adds executable code to the interface and possibly with it the need to save state:
In C# 8.0 Microsoft has introduced default interface methods. It is optional for a class to implement these methods. If they are not implemented, the default implementations kick in. However, these methods are not inherited by the class and can only be called through the interface (even within the class implementing the interface).
The primary motivation is to allow extending an interface without breaking existing code.
Static fields and other members not being part of the public interface are there to support the implementation of those default interface methods. The C# language proposal for default interface methods says:
Interfaces may not contain instance state. While static fields are now permitted, instance fields are not permitted in interfaces. Instance auto-properties are not supported in interfaces, as they would implicitly declare a hidden field.
Static and private methods permit useful refactoring and organization of code used to implement the interface's public API.
Yet another feature is coming with C# 11: static virtual members in interfaces. Those must be implemented by the implementing class. They were primarily introduced to allow formulating interfaces for numeric types who have static operator methods (+, -, *, /, etc.). But they also allow to declare static factory methods. These interfaces are useful in generic type constraints.
Here is a full use case. New properties are added to an interface. To not break existing implementations, they are added with a default implementation.
Since we cannot store instance state in an interface (interfaces are not instantiated), we cannot use instance backing fields for the properties. Instead, we use a dictionary with object references as key to store the property values. (We could also use Weak References, but that's beyond the scope of this article.) The dictionary is stored in a private static field. This is comparable to how WPF stores dependency properties.
interface IUseCase
{
string Name { get; set; } // Public by default, must be implemented by the class
// New property added in a later release with a default implementation.
// Implementation by class is optional.
private static Dictionary<IUseCase, string?> _firstNames =
new(ReferenceEqualityComparer.Instance);
string? FirstName
{
get {
_firstNames.TryGetValue(this, out string? s);
return s; // s is null when TryGetValue returns false
}
set {
_firstNames[this] = value;
}
}
// New property with default implementation.
string FullName => $"{FirstName} {Name}";
}
A class created before the interface was extended implementing only the first property.
class UseCase : IUseCase
{
public UseCase(string name)
{
Name = name;
}
public string Name { get; set; }
}
Test:
IUseCase u1 = new UseCase("Doe");
u1.FirstName = "John";
IUseCase u2 = new UseCase("Poe");
u2.FirstName = "Jane";
Console.WriteLine(u1.FullName);
Console.WriteLine(u2.FullName);
Prints:
John Doe
Jane Poe
It looks like there are two main reasons such as
to store a value that must be shared among all instances
you can count some value between all instances
to avoid recreation of an instance of static field value each time
Let me show a example:
public interface IFoo
{
private static string staticField;
public static string GetStaticField()
{
if (staticField is null)
staticField = $"DateTime is {DateTime.Now}";
return staticField;
}
}
or shorter version will look like this:
public static string GetStaticField()
{
staticField ??= $"DateTime is {DateTime.Now}";
return staticField;
}
and then it can be seen that if staticField will be assigned, then it never be reassigned:
var result_1 = IFoo.GetStaticField();
Console.WriteLine(result_1);
Thread.Sleep(10000); // imitation of hard work
var result_2 = IFoo.GetStaticField();
Console.WriteLine(result_2);
Output:
DateTime is 2022.10.12 05:10
DateTime is 2022.10.12 05:10
I'm currently modifying a Blazor library and the souce code of the current state is available on gitlab.
My situation is as follows:
I have a LineChartData object which is supposed to store multiple Datasets for LineCharts.
These Datasets intern have a List of Data. Instead of just working with List<object> I wanted to be able to have List<TData>.
Because there is a Mixed Chart which can accept both LineChartDatasets and BarChartDatasets, there is an interface called IMixableDataset.
I started by making this interface generic so it now looks like this (simplified):
public interface IMixableDataset<TData>
{
List<TData> Data { get; }
}
I then made my implementing class (LineChartDataset) generic as well and it now looks like this (simplified):
public class LineChartDataset<TData> : IMixableDataset<TData>
{
public List<TData> Data { get; }
}
Next up was LineChartData. I first made this generic as well and continued with that until I reached the top level (see current state of my master branch). However I later wanted to change this because I wanted to support multiple Datasets with different kind of values. For this reason I reverted the generic stuff in all classes "above" the Datasets and the LineChartData now looks like this (simplified):
public class LineChartData
{
// HashSet to avoid duplicates
public HashSet<LineChartDataset<object>> Datasets { get; }
}
I decided to go with LineChartDataset<object> because: Since everything is castable to object, (in my mind) XYZ<Whatever> should also be castable to XYZ<object> but as I learned, this is not the case.
The where keyword didn't help either since I don't want to enforce TData to have relations apart from object - it could be int, string or something completely different. The only relation these LineDatasets are supposed to have is that they are LineDatasets, not what type they contain.
I then learned about Covariance and Contravariance (out and in-keyword). I tried out to make TData in IMixableDataset covariant but since List and IList/ICollection are all invariant I was unable to persue.
I also read about IReadOnlyCollection<> which is covariant but I cannot use this because I have to be able to modify the list after creation.
I have also tried using implicit/explicit operators to convert LineChartDataset<whatever> to LineChartDataset<object> but this has a few issues:
Since I created a new instance, I would need to store and use the new instance instead of the original one to add items, completely destroying the typesafety I had with the original one.
Since there are many more properties in LineChartDataset I would have to clone all of them as well.
If there is a way to convert a more specific one to the other while preserving the instance and not having to write code for every property this might be a solution.
Complete sample which reproduces the error I get and shows the issue:
// Provides access to some Data of a certain Type for multiple Charts
public interface IMixableDataset<TData>
{
List<TData> Data { get; }
}
// Contains Data of a certain Type (and more) for a Line-Chart
public class LineChartDataset<TData> : IMixableDataset<TData>
{
public List<TData> Data { get; } = new List<TData>();
}
// Contains Datasets (and more) for a Line-Chart
// This class should not be generic since I don't want to restrict what values the Datasets have.
// I only want to ensure that each Dataset intern only has one type of data.
public class LineChartData
{
// HashSet to avoid duplicates and Public because it has to be serialized by JSON.Net
public HashSet<LineChartDataset<object>> Datasets { get; } = new HashSet<LineChartDataset<object>>();
}
// Contains the ChartData (with all the Datasets) and more
public class LineChartConfig
{
public LineChartData ChartData { get; } = new LineChartData();
}
public class Demo
{
public void DesiredUseCase()
{
LineChartConfig config = new LineChartConfig();
LineChartDataset<int> intDataset = new LineChartDataset<int>();
intDataset.Data.AddRange(new[] { 1, 2, 3, 4, 5 });
config.ChartData.Datasets.Add(intDataset);
// the above line yields following compiler error:
// cannot convert from 'Demo.LineChartDataset<int>' to 'Demo.LineChartDataset<object>'
// the config will then get serialized to json and used to invoke some javascript
}
public void WorkingButBadUseCase()
{
LineChartConfig config = new LineChartConfig();
LineChartDataset<object> intDataset = new LineChartDataset<object>();
// this allows mixed data which is exactly what I'm trying to prevent
intDataset.Data.AddRange(new object[] { 1, 2.9, 3, 4, 5, "oops there's a string" });
config.ChartData.Datasets.Add(intDataset); // <-- No compiler error
// the config will then get serialized to json and used to invoke some javascript
}
}
The reason everything only has getters is because of my initial attempt with using out. Even thought this didn't work out, I learned that you usually don't expose Setters for Collection-properties. This is not fix and also not very important for the question but I think worth mentioning.
Second complete example. Here I'm using out and an IReadOnlyCollection. I have removed the descriptions of the class (already visible in the previous example) to make it shorter.
public interface IMixableDataset<out TData>
{
IReadOnlyCollection<TData> Data { get; }
}
public class LineChartDataset<TData> : IMixableDataset<TData>
{
public IReadOnlyCollection<TData> Data { get; } = new List<TData>();
}
public class LineChartData
{
public HashSet<IMixableDataset<object>> Datasets { get; } = new HashSet<IMixableDataset<object>>();
}
public class LineChartConfig
{
public LineChartData ChartData { get; } = new LineChartData();
}
public class Demo
{
public void DesiredUseCase()
{
LineChartConfig config = new LineChartConfig();
IMixableDataset<int> intDataset = new LineChartDataset<int>();
// since it's ReadOnly, I of course can't add anything so this yields a compiler error.
// For my use case, I do need to be able to add items to the list.
intDataset.Data.AddRange(new[] { 1, 2, 3, 4, 5 });
config.ChartData.Datasets.Add(intDataset);
// the above line yields following compiler error (which fairly surprised me because I thought I correctly used out):
// cannot convert from 'Demo.IMixableDataset<int>' to 'Demo.IMixableDataset<object>'
}
}
So the question:
Is there anyway to have a mutable and covariant collection?
If not, is there a workaround or something I can do to achieve this functionality?
Additional stuff:
I'm using the newest version of everything (.net core, VS, blazor, C#). Since the library is .NET Standard I'm still on C# 7.3 there.
In the repo under WebCore/Pages/FetchData you can perfectly see what I want to achieve (see comments at the end of the file).
Looking more closely at your example, I see one major problem: you are attempting to involve value types (e.g. int) in type variance. For better or worse, C# type variance applies only to reference types.
So, no…sorry, but it is quite impossible to do exactly what you're asking. You would have to represent all value-type based collections as object, not as their specific value types.
Now, as far as reference-type collections go, your example will work fine, with one minor change. Here's a modified version of your second example showing it working, with that one minor change:
public interface IMixableDataset<out TData>
{
IReadOnlyCollection<TData> Data { get; }
}
public class LineChartDataset<TData> : IMixableDataset<TData>
{
private readonly List<TData> _list = new List<TData>();
public IReadOnlyCollection<TData> Data => _list;
public void AddRange(IEnumerable<TData> collection) => _list.AddRange(collection);
}
public class LineChartData
{
public HashSet<IMixableDataset<object>> Datasets { get; } = new HashSet<IMixableDataset<object>>();
}
public class LineChartConfig
{
public LineChartData ChartData { get; } = new LineChartData();
}
public class Demo
{
public void DesiredUseCase()
{
LineChartConfig config = new LineChartConfig();
// Must use reference types to take advantage of type variance in C#
LineChartDataset<string> intDataset = new LineChartDataset<string>();
// Using the non-interface method to add the range, you can still mutate the object
intDataset.AddRange(new[] { "1", "2", "3", "4", "5" });
// Your original code works fine when reference types are used
config.ChartData.Datasets.Add(intDataset);
}
}
In particular, note that I've added an AddRange() method to your LineChartDataset<TData> class. This provides a type-safe way to mutate the collection. Note that the code that wants to mutate the collection must know the correct type, bypassing the variance restrictions.
The variant interface IMixableDataset<TData> itself cannot, of course, include a way to add things, because this would not be type-safe. You would be able to treat your LineChartDataset<string> as a IMixableDataset<object>, and then if you could add things via that interface, you'd be able to add some other type of object, even a non-reference type like a boxed int value, to your collection that's supposed to only contain string objects.
But, just as the invariant List<T> can implement the covariant IReadOnlyCollection<T>, your concrete LineChartDataset<TData> class can implement IMixableDataset<TData> while still providing a mechanism for adding items. This works because while the concrete type determines what the object can actually do, the interfaces simply define a contract that users of the reference must abide by, allowing the compiler to ensure type safety where the interface is used, even when used in a variant way. (The invariant concrete type ensures type safety as well, but only because the type has to match exactly, which is of course more restrictive/less flexible.)
If you don't mind using object in place of any specific value type for the value-type-based collections, then the above would work. It's a bit clumsy, since any time you actually want to get the value type values out, you'd need to retrieve them as object and then cast as necessary to actually use them. But at least the broader variant approach would then succeed, and no special handling would be required for any reference types.
Aside: that type variance in C# is restricted to reference types is based on the pragmatic requirement that type variance doesn't affect the runtime code. It's just a compile-time type-conversion. This means that you have to be able to just copy references around. To support value types would require adding new boxing and unboxing logic where it otherwise wouldn't exist. It's also not quite as useful, because value types don't have the same rich degree of type inheritance that reference types can have (value types can only ever inherit object, so variant scenarios are much less useful and interesting, in general).
Intro
I'm working with the legacy code which contains two classes:
I have a class which stores its value of System.Object type.
(I named this class as DomainItem)
Its Identifier property refers to
enum which holds information what a type of DomainItem is (in the
context of business domain).
There is also a class which stores these
items as an Enumerable List. (DomainItems)
What's more:
I don't want to change these classes into generic. This code is very sensitive and not covered by tests.
In order to get DomainItem, I must get it from DomainItems.Items collection.
Code
The code for classes is equivalent as below:
public class DomainItem
{
public Identifier Identifier { get; set; } // Readonly in the "real" code
public object Value { get; set; }
}
public class DomainItems
{
public IEnumerable<DomainItem> Items { get; set; }
}
The question is
How can I extend these classes using generics, to resolve type of Value property in the compile time. Is it even possible?
Example case might be as following:
DomainItem price = new DomainItem { Value = 25.20d, Identifier = Identifier.Price };
// ....
double priceValue = price.ProperValue; // generic property of type T
Obviously, above code is conceptual and it shows what I want to achieve. Any suggestions how to resolve that? Is it even possible?
Edit
My idea is to create a new IEnumerable<DomainItem<T>> where the collection is populated from non-generic DomainItem objects. Since the type of DomainItem.Value is known, it should be possible to make such collection somehow.
There's no such thing as a generic property, but you could easily create a generic method:
public T GetValue<T>() { ... }
public void SetValue<T>(T value) { ... }
You could then check typeof(T) within the method to make sure that it was appropriate for your identifier, ideally having made the identifier read-only. (It would be better as a constructor argument - I wouldn't expect it to make any sense to have a domain item whose identifier changed over time.)
Alternatively, you could just make the type of the Value property dynamic instead of object, assuming you're using C# 4+ with .NET 4+. Then your example code would compile - but it would perform an implicit (dynamic) conversion to double at execution time. You wouldn't get much safety there, but it would compile...
I am trying to find a better way to handle some growing if constructs to handle classes of different types. These classes are, ultimately, wrappers around disparate value types (int, DateTime, etc) with some additional state information. So the primary difference between these classes is the type of data they contain. While they implement generic interfaces, they also need to be kept in homogeneous collections, so they also implement a non-generic interface. The class instances are handled according to the type of data they represent and their propogation continues or doesn't continue based on that.
While this is not necessarily a .NET or C# issue, my code is in C#.
Example classes:
interface ITimedValue {
TimeSpan TimeStamp { get; }
}
interface ITimedValue<T> : ITimedValue {
T Value { get; }
}
class NumericValue : ITimedValue<float> {
public TimeSpan TimeStamp { get; private set; }
public float Value { get; private set; }
}
class DateTimeValue : ITimedValue<DateTime> {
public TimeSpan TimeStamp { get; private set; }
public DateTime Value { get; private set; }
}
class NumericEvaluator {
public void Evaluate(IEnumerable<ITimedValue> values) ...
}
I have come up with two options:
Double Dispatch
I recently learned of the Visitor pattern and its use of double dispatch to handle just such a case. This appeals because it would allow undesired data to not propogate (if we only want to handle an int, we can handle that differently than a DateTime). Also, the behaviors of how the different types are handled would be confined to the single class that is handling the dispatch. But there is a fair bit of maintenance if/when a new value type has to be supported.
Union Class
A class that contains a property for each value type supported could be what each of these classes store. Any operation on a value would affect the appropriate component. This is less complex and less maintenance than the double-dispatch strategy, but it would mean that every piece of data would propogate all the way through unnecessarily as you can no longer discriminate along the lines of "I don't operate upon that data type". However, if/when new types need to be supported, they only need to go into this class (plus whatever additional classes that need to be created to support the new data type).
class UnionData {
public int NumericValue;
public DateTime DateTimeValue;
}
Are there better options? Is there something in either of these two options that I did not consider that I should?
method 1, using dynamic for double dispatch (credit goes to http://blogs.msdn.com/b/curth/archive/2008/11/15/c-dynamic-and-multiple-dispatch.aspx).
Basically you can have your Visitor pattern simplified like this:
class Evaluator {
public void Evaluate(IEnumerable<ITimedValue> values) {
foreach(var v in values)
{
Eval((dynamic)(v));
}
}
private void Eval(DateTimeValue d) {
Console.WriteLine(d.Value.ToString() + " is a datetime");
}
private void Eval(NumericValue f) {
Console.WriteLine(f.Value.ToString() + " is a float");
}
}
sample of usage:
var l = new List<ITimedValue>(){
new NumericValue(){Value= 5.1F},
new DateTimeValue() {Value= DateTime.Now}};
new Evaluator()
.Evaluate(l);
// output:
// 5,1 is a float
// 29/02/2012 19:15:16 is a datetime
method 2 would use Union types in c# as proposed by #Juliet here (alternative implementation here)
I tell you have I've solved a similar situation - is by storing the Ticks of a DateTime or TimeSpan as double in the collection and by using IComparable as a where constraint on the type parameter. The conversion to double / from double is performed by a helper class.
Please see this previous question.
Funnily enough this leads to other problems, such as boxing and unboxing. The application I am working on requires extremely high performance so I need to avoid boxing. If you can think of a great way to generically handle different datatypes (including DateTime) then I'm all ears!
Good question. The first thing that came to my mind was a reflective Strategy algorithm. The runtime can tell you, either statically or dynamically, the most derived type of the reference, regardless of the type of the variable you are using to hold the reference. However, unfortunately, it will not automatically choose an overload based on the derived type, only the variable type. So, we need to ask at runtime what the true type is, and based on that, manually select a particular overload. Using reflection, we can dynamically build a collection of methods identified as handling a particular sub-type, then interrogate the reference for its generic type and look up the implementation in the dictionary based on that.
public interface ITimedValueEvaluator
{
void Evaluate(ITimedValue value);
}
public interface ITimedValueEvaluator<T>:ITimedValueEvaluator
{
void Evaluate(ITimedValue<T> value);
}
//each implementation is responsible for implementing both interfaces' methods,
//much like implementing IEnumerable<> requires implementing IEnumerable
class NumericEvaluator: ITimedValueEvaluator<int> ...
class DateTimeEvaluator: ITimedValueEvaluator<DateTime> ...
public class Evaluator
{
private Dictionary<Type, ITimedValueEvaluator> Implementations;
public Evaluator()
{
//find all implementations of ITimedValueEvaluator, instantiate one of each
//and store in a Dictionary
Implementations = (from t in Assembly.GetCurrentAssembly().GetTypes()
where t.IsAssignableFrom(typeof(ITimedValueEvaluator<>)
and !t.IsInterface
select new KeyValuePair<Type, ITimedValueEvaluator>(t.GetGenericArguments()[0], (ITimedValueEvaluator)Activator.CreateInstance(t)))
.ToDictionary(kvp=>kvp.Key, kvp=>kvp.Value);
}
public void Evaluate(ITimedValue value)
{
//find the ITimedValue's true type's GTA, and look up the implementation
var genType = value.GetType().GetGenericArguments()[0];
//Since we're passing a reference to the base ITimedValue interface,
//we will call the Evaluate overload from the base ITimedValueEvaluator interface,
//and each implementation should cast value to the correct generic type.
Implementations[genType].Evaluate(value);
}
public void Evaluate(IEnumerable<ITimedValue> values)
{
foreach(var value in values) Evaluate(value);
}
}
Notice that the main Evaluator is the only one that can handle an IEnumerable; each ITimedValueEvaluator implementation should handle values one at a time. If this isn't feasible (say you need to consider all values of a particular type), then this gets really easy; just loop through every implementation in the Dictionary, passing it the full IEnumerable, and have those implementations filter the list to only objects of the particular closed generic type using the OfType() Linq method. This will require you to run all ITimedValueEvaluator implementations you find on the list, which is wasted effort if there are no items of a particular type in a list.
The beauty of this is its extensibility; to support a new generic closure of ITimedValue, just add a new implementation of ITimedValueEvaluator of the same type. The Evaluator class will find it, instantiate a copy, and use it. Like most reflective algorithms, it's slow, but the actual reflective part is a one-time deal.
Why not just implement the interface that you actually want, and allow the implementing type to define what the value is? For example:
class NumericValue : ITimedValue<float> {
public TimeSpan TimeStamp { get; private set; }
public float Value { get; private set; }
}
class DateTimeValue : ITimedValue<DateTime>, ITimedValue<float> {
public TimeSpan TimeStamp { get; private set; }
public DateTime Value { get; private set; }
public Float ITimedValue<Float>.Value { get { return 0; } }
}
class NumericEvaluator {
public void Evaluate(IEnumerable<ITimedValue<float>> values) ...
}
If you want the behavior of the DateTime implementation to vary based on the particular usage (say, alternate implementations of Evaluate functions), then they by definition need to be aware of ITimedValue<DateTime>. You can get to a good statically-typed solution by providing one or more Converter delegates, for example.
Finally, if you really only want to handle the NumericValue instances, just filter out anything that isn't a NumericValue instance:
class NumericEvaluator {
public void Evaluate(IEnumerable<ITimedValue> values) {
foreach (NumericValue value in values.OfType<NumericValue>()) {
....
}
}
}
I'm using a 3rd party's set of webservices, and I've hit a small snag. Before I manually make a method copying each property from the source to the destination, I thought I'd ask here for a better solution.
I've got 2 objects, one of type Customer.CustomerParty and one of type Appointment.CustomerParty. The CustomerParty objects are actually property and sub-oject exactly the same. But I can't cast from 1 to the other.
So, I need to find a certain person from the webservice. I can do that by calling Customer.FindCustomer(customerID) and it returns a Customer.CustomerParty object.
I need to take that person that I found and then use them a few lines down in a "CreateAppointment" request. Appointment.CreateAppointment takes an appointment object, and the appointment object contains a CustomerParty object.
However, the CustomerParty object it wants is really Appointment.CustomerParty. I've got a Customer.CustomerParty.
See what I mean? Any suggestions?
Why don't you use AutoMapper? Then you can do:
TheirCustomerPartyClass source = WebService.ItsPartyTime();
YourCustomerPartyClass converted =
Mapper.Map<TheirCustomerPartyClass, YourCustomerPartyClass>(source);
TheirCustomerPartyClass original =
Mapper.Map<YourCustomerPartyClass, TheirCustomerPartyClass>(converted);
As long as the properties are identical, you can create a really simple map like this:
Mapper.CreateMap<TheirCustomerPartyClass, YourCustomerPartyClass>();
Mapper.CreateMap<YourCustomerPartyClass, TheirCustomerPartyClass>();
This scenario is common when writing domain patterns. You essentially need to write a domain translator between the two objects. You can do this several ways, but I recommend having an overridden constructor (or a static method) in the target type that takes the service type and performs the mapping. Since they are two CLR types, you cannot directly cast from one to the other. You need to copy member-by-member.
public class ClientType
{
public string FieldOne { get; set; }
public string FieldTwo { get; set; }
public ClientType()
{
}
public ClientType( ServiceType serviceType )
{
this.FieldOne = serviceType.FieldOne;
this.FieldTwo = serviceType.FieldTwo;
}
}
Or
public static class DomainTranslator
{
public static ServiceType Translate( ClientType type )
{
return new ServiceType { FieldOne = type.FieldOne, FieldTwo = type.FieldTwo };
}
}
I'm using a 3rd party's set of
webservices...
Assuming you can't modify the classes, I'm not aware of any way you can change the casting behavior. At least, no way that isn't far, far more complicated than just writing a CustomerToAppointmentPartyTranslator() mapping function... :)
Assuming you're on a recent version of C# (3.5, I believe?), this might be a good candidate for an extension method.
Have you looked at adding a conversion operator to one of the domain classes to define an explicit cast. See the msdn documentation here.
Enjoy!
A simple and very fast way of mapping the types is using the PropertyCopy<TTarget>.CopyFrom<TSource>(TSource source)
method from the MiscUtil library as described here:
using MiscUtil.Reflection;
class A
{
public int Foo { get; set; }
}
class B
{
public int Foo { get; set; }
}
class Program
{
static void Main()
{
A a = new A();
a.Foo = 17;
B b = PropertyCopy<B>.CopyFrom(a);
bool success = b.Foo == 17; // success is true;
}
}
Two classes with exactly the same signature, in two different namespaces, are two different classes. You will not be able to implicitly convert between them if they do not explicitly state how they can be converted from one to the other using implicit or explicit operators.
There are some things you may be able to do with serialization. WCF DataContract classes on one side do not have to be the exact same type as the DataContract on the other side; they just have to have the same signature and be decorated identically. If this is true for your two objects, you can use a DataContractSerializer to "convert" the types through their DataContract decoration.
If you have control over the implementation of one class or the other, you can also define an implicit or explicit operator that will define how the other class can be converted to yours. This will probably simply return a new reference of a deep copy of the other object in your type. Because this is the case, I would define it as explicit, to make sure the conversion is only performed when you NEED it (it will be used in cases when you explicitly cast, such as myAppCustomer = (Appointment.CustomerParty)myCustCustomer;).
Even if you don't control either class, you can write an extension method, or a third class, that will perform this conversion.