Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this questionI've been thinking about a possible usage of dynamic keyword.
Being a big defender (say it paladin) of strongly-typed programming languages, I needed to open my mind a lot and try to think an alternative way of doing things.
Some thing I found hard to mantain is how layers and tiers are communicated with data transfer objects (DTO).
How many dozens of DTOs have you needed to cover transferring data through your application or service? I'm sure we can count a lot of them in any well-done project.
But, what about the domain object-to-DTO translation? You end up creating dozens of DTO which transfer info from a number of domain objects evolved in some transaction, flow or process.
In the end, what are the most important things to keep in mind when you develop software? - Money and/or time first. Sizing the project to cover it with the right solution with available resources. - Create a maintainable, scalable, performant, well-designed application. Everything with our limited resources.
Talking about the second point, what is maintanable and scalable? A incredibly well-done design which has thousands of classes, interfaces, ... to maintain and improve? Yes. Think in a well-done DDD, MVC, solution. Easy to follow, improve, fix... But not in terms of time. You can do it right, but you'll need a lot of time.
Perhaps there's a solution for that with the flagship Dynamic Language Runtime and associated "dynamic" keyword in C# 4.0 on top of .NET Framework 4.0.
Yes, dynamic seems evil if it's not for interop or working with dynamic languages... Right! But, remembering what I said in the second sentence, I wanted to go forward and think about this topic.
We've tuples. Good! We can have typed multiple results as a return value in a method or property. We don't need custom DTO! Wrong because we don't have named tuples. How can we mantain a code that's giving results with properties like "Item1, Item2, ItemN".
Tuples seem to be a good solution for example for replacing the usage of "out" keyword in methods like bool TryParse(value, out result) into Tuple TryParse(T value), but I don't think this is a good replacement for DTO, because we're loosing the meaning of the code... Code is readable no more.
Later, I was thinking in how to create attribute-based named tuples, but it has a drawback: you need reflection to get something like 'tuple.Return("Name")' work fine. Discarded.
It was at this point when I thought, what about dynamic and DLR? I was figuring out how to do dynamic tuples and work with them.
Something like this is possible, but I want to discuss with you if you find that fine or not:
public static class DynamicTupleExtensions
{
public static dynamic Return(this IEnumerable source, Func returnPredicate)
{
return source.Select(result => returnPredicate(result)).Single();
}
public static IEnumerable> ToTuple(this IEnumerable source)
{
return source.Select(dynamicTuple => Tuple.Create((T1)dynamicTuple.GetType().GetProperties()[0].GetValue(dynamicTuple, null)));
}
public static IEnumerable Cast(this IEnumerable source)
{
return source.Select(dynamicTuple => JsonConvert.DeserializeObject(JsonConvert.SerializeObject(dynamicTuple)));
}
public static T Cast(this object source)
where T : class
{
return JsonConvert.DeserializeObject(JsonConvert.SerializeObject(source));
}
}
public class StronglyTypedResult
{
public int Value
{
get;
set;
}
}
public class Program
{
private static void Main(string[] args)
{
int result = AddOne(10).Return(value => value.Value);
Tuple resultAsTuple = AddOne(10).ToTuple().Single();
StronglyTypedResult typedResult = AddOne(10).Cast().Single();
Console.WriteLine(result);
Console.Read();
}
private static IEnumerable AddOne(int value)
{
return new List
{
new { Value = value + 1 }
};
}
}
Looking at the code, you'll see that I'm "abussing" of anonymous types and dynamic keyword in order to create an enumerable of dynamic tuples.
Later, you can retrieve dynamic tuple value by using three approaches: - Full dynamic-based tuple retrieval. - Convert to a typed tuple. - Cast as DTO (it's a conversion).
First one is the most controversial one: it's a full dynamic tuple consumed "as is". You lose compile-time type checking, but you gain a lot of flexibility. I would use it in a project with high discipline and a strong naming and convention guidelines (this is heaven, I know it).
Second one it's a mix of compile-time and run-time type checking: the tuple is dinamically handled, but you get a strongly-typed tuple. That's loosing the named tuple-like solution in the first approach. This approach would be for use in a method body, where maybe there's no access to the classes representing DTO or you don't have them, or there's no implementation for them (same as first option).
Finally, the third one is the safest solution: you use dynamic tuples in some layer or tier, and wherever you've classes representing DTOs, you cast the dynamic tuple to DTO and this is working as actual and most of C# DTOs. This isn't a 开发者_开发百科good option because I'm using a JSON serializer in order to lie C# compiler and make an on-the-fly converstion from the anonymous type to the strongly-typed DTO.
At the end of the day, which is the question? The question is, what's your opinion about this solution?
It's maintainable?
What would be the performance impact of such approach?
Do you think that discipline is the only requirement to follow this approach or it's just a big fail?
Do you think that this solution is a big fail and it's a big crash in terms of creating well-designed solutions?
It's just software philosophy. And I'm pretty sure that this approaching is going to have defenders and haters.
Keep in mind that this isn't "the asker thinks that this is the best solution", but I'm just throwing here a conclusion I want to share with everyone.
Thanks for reading and I hope you all are going to have good points (even if you hate my conclusions, it's about that!).
At the end (after one or 2 years) your early discussion have became true and more popular (check here) with the "Dynamic model binding with ASP.NET WEB API". The basic idea it's to avoid the amount of DTOs using dynamics and this way increasing the flexibility.
public Class Controller : APIController()
{
public dynamic Post(dynamic contract)
{
return contract;
}
}
It seems like you are looking for a combination of AutoMapper Dynamic Mapping and the ExpandoObject. With some creative reflection, you could probably accomplish your goal in this way.
精彩评论