I am obviously doing something wrong here, but the question is how do i get it working? I got the following code
Note: ParameterEventStreamRef inherits from Parameter, same goes for the StStvariants.
public void DoStuff(Parameter[] parameters)
{
var Parameters = parameters.Select(x => parameterConverterFactory.GetParameterConverter(x).ToJsonClass(x)).ToArray();
}
public class ParameterConverterFactory: IParameterConverterFactory
{
public IStackStateJsonConverter<StStParameter, Parameter> GetParameterConverter(StStParameter arg)
{
if (arg.GetType() == typeof(StStParameterEventStreamRef))
return new JsonParameterEventStreamRefConverter();
throw new InvalidEnumArgumentException(arg.GetType().FullName);
}
public class JsonParameterEventStreamRefConverter : JsonParameterConverter, IStackStateJsonConverter<StStParameterEventStreamRef, ParameterEventStreamRef>
{
public ParameterEventStreamRef ToJsonClass(StStParameterEventStreamRef arg, ParameterEventStreamRef source = null)
{
if (source == null)
source = new ParameterEventStreamRef();
base.ToJsonClass(arg, source);
source.var1 = arg.var1;
source.var2 = arg.var2;
return source;
}
}
public class JsonParameterConverter : JsonNodeConverter, IStackStateJsonConverter<StStParameter, Parameter>
{
public Parameter ToJsonClass(StStParameter arg, Parameter source = null)
{
if (source == null)
source = new Parameter();
source.var0 = arg.var0;
return source;
}
}
Problem is: the factory is returning the correct Converter, but when the converter is called, it is "Skipping" the JsonParameterEventStreamRefConverter and going directly to the JsonParameterConverter. I think the reason for this is a part of the logic is done compile-time, the other run-time.
In DoStuff() you're calling the ToJsonClass() method. Even though that you 'x' could be any descendant from Parameter, the runtime will not know which one it is.
It will look for the ToJsonClass() signature that best matches the signature: ToJsonClass(Parameter). The JsonParamterConverter has a method that matches this exactly, so that's the best match.
You could try replacing the ToJsonClass() in JsonParameterStreamRef with something like this:
public override Parameter ToJsonClass(StStParameter arg, Parameter source = null)
{
if (arg.GetType() == typeof (StStParameterEventStreamRef))
{
return ToJsonClass(arg as StStParameterEventStreamRef, source as ParameterEventStreamRef);
}
return base.ToJsonClass(arg, source); // or throw an exception if this is an error.
}
The following is a working solution to the problem, but if you can come up with a better solution, please.
public Parameter GetConverterFactory_AndDo_ToJsonClass(StStParameter stStParameter)
{
if (stStParameter.GetType() == typeof (StStParameterEventStreamRef))
return new JsonParameterEventStreamRefConverter().ToJsonClass(stStParameter as StStParameterEventStreamRef);
throw new InvalidEnumArgumentException(stStParameter.GetType().FullName);
}
Related
I have this
public static class Parameters
{
public static void Required<T>(this T parameter, string paramName) where T : class
{
if (parameter == null)
{
throw new ArgumentNullException(paramName);
}
// ...
}
}
And I use it like:
Parameters.Required(settings, nameof(settings));
Is it possible to get rid of the second parameter and somehow get the original parameter name, from within the Required method? No, right?
You could make the Requred-function accepting a Expression. And from the expression you can read out the name of the member name. It's descriped here.
public static void Required<T>(Expression<Func<T>> parameter) where T : class
{
if (parameter.Compile().Invoke() == null)
{
var caller = ((MemberExpression)parameter.Body).Member.Name;
throw new ArgumentNullException(caller);
}
// ...
}
and call it like this:
Parameters.Required(() => settings);
Trying to write a utilty method which determines whether a type is parseable (i.e. has a method like: Parse(string value)
The code below works, but seems a bit kludgey:
public static bool IsParseable(Type t) {
string s = "foo";
Type[] typeArray = { s.GetType() };
if (t.GetRuntimeMethod("Parse", typeArray )==null) {
return false;
} else {
return true;
}
}
It seems like there should be a better way to get my hands on String type then having to create an instance of the type (string) in order to call GetType()
This likewise comes up trying to use the method, as in:
bool results = IsParseable(Double); //doesn't compile.
Instead to find out if double is parseable, I have to do something like.
Double v = 1.0;
Type doubleType = v.GetType();
bool result = IsParseable(doubleType);
Is there a more efficient way? Ultimately I want to use this with generic types, where I have a type parameter T and I want to find out if T has a Parse(String value) method:
IsParseable(T)
which of course doesn't work either. And creating an instance of T isn't a great solution because not known if T has a default constructor.
You can use generic approach
public static bool IsParseable<T>()
{
var argumentTypes = new[] { typeof(string) };
var type = typeof(T);
return type.GetRuntimeMethod("Parse", argumentTypes) != null;
}
// Use it
if (IsParseable<decimal>())
{
// Parse...
}
Or use your approach with Thomas Weller's hint and make method an extension method for Type (even better from readability point of view (opinion based)).
public static bool IsParseable(this Type type)
{
var argumentTypes = new[] { typeof(string) };
return type.GetRuntimeMethod("Parse", argumentTypes) != null;
}
Then use
if (typeof(decimal).IsParseable())
{
// Do something
}
Do you know a better way (more pretty) than below to throw an exception?
public long GetPlaylistId(long songInPlaylistId)
{
var songInPlaylist = service.GetById(songInPlaylistId);
return songInPlaylist
.With(x => x.Playlist)
.ReturnValueOrException(x => x.Id,
new ArgumentException(
"Bad argument 'songInPlaylistId'"));
}
Monadic extension methods:
public static TResult With<TInput, TResult>(this TInput obj,
Func<TInput, TResult> evaluator)
where TInput : class
where TResult : class
{
return obj == null ? null : evaluator(obj);
}
public static TResult ReturnValueOrException<TInput, TResult>(
this TInput obj, Func<TInput, TResult> evaluator, Exception exception)
where TInput : class
{
if (obj != null)
{
return evaluator(obj);
}
throw exception;
}
If it is valid to try to get the playlist for something that doesn't have a playlist, then you should not throw an exception but should just return a special value that means "not found" instead (for example, 0 or -1 depending on how your playlist IDs work).
Alternatively you could write a TryGetPlaylistId() method which works in a similar way to Microsoft's TryXXX() methods (e.g. SortedList.TryGetValue()), for example:
public bool TryGetPlaylistId(long songInPlaylistId, out long result)
{
result = 0;
var songInPlaylist = service.GetById(songInPlaylistId);
if (songInPlaylist == null)
return false;
if (songInPlaylist.Playlist == null)
return false;
result = songInPlaylist.Playlist.Id;
return true;
}
A small problem with this approach is that you are obscuring information that might be of use when trying to diagnose issues. Perhaps adding Debug.WriteLine() or some other form of logging would be of use. The point being, you can't differentiate between the case where the playlist ID is not found, and the case where it is found but doesn't contain a playlist.
Otherwise, you could throw an exception which has a more informative message, for example:
public long GetPlaylistId(long songInPlaylistId)
{
var songInPlaylist = service.GetById(songInPlaylistId);
if (songInPlaylist == null)
throw new InvalidOperationException("songInPlaylistId not found: " + songInPlaylistId);
if (songInPlaylist.Playlist == null)
throw new InvalidOperationException("Playlist for ID " + songInPlaylistId " has no playlist: ");
return songInPlaylist.Playlist.Id;
}
It might be the case that it is valid to not find the song in the playlist, but it is NOT valid to find one which does not have a playlist, in which case you would return a special value in the first case and throw an exception in the second case, for example:
public long GetPlaylistId(long songInPlaylistId)
{
var songInPlaylist = service.GetById(songInPlaylistId);
if (songInPlaylist == null)
return -1; // -1 means "playlist not found".
if (songInPlaylist.Playlist == null)
throw new InvalidOperationException("Playlist for ID " + songInPlaylistId " has no playlist: ");
return songInPlaylist.Playlist.Id;
}
In any case, I personally think that your extension methods are just obscuring the code.
try{
if (obj != null)
{
return evaluator(obj);
}
}
catch(Exception ex)
{
throw;
}
return obj;
You should not throw error unless caught in to some. Better return null in the given case and handle it in your calling code:
And what will happen if I have more than one such ambiguous methods in my class? It's very difficult to invent different rules for any method. You will be confused in the end.
What do you think about this solution?
public class ApplicationResponse
{
public IList<string> Errors { get; set; }
public dynamic Data { get; set; }
public bool HasErrors()
{
return Errors != null && Errors.Any();
}
}
public ApplicationResponse GetPlaylistId(long songInPlaylistId)
{
var songInPlaylist = service.GetById(songInPlaylistId);
if (songInPlaylist == null)
{
return new ApplicationResponse { Errors = new[] { "Song was not found." } };
}
if (songInPlaylist.Playlist == null)
{
return new ApplicationResponse { Errors = new[] { "Playlist was not found." } };
}
return new ApplicationResponse { Data = songInPlaylist.Playlist.Id };
}
public HttpResponseMessage SomeRequest([FromUri] songInPlaylistId)
{
var response = appService.GetPlaylistId(long songInPlaylistId);
if (response.HasErrors())
{
// reply with error status
}
// reply with ok status
}
In such case I can send all the errors to a client.
I am trying to build a method to check if a list is empty:
public static T1 NotEmpty<T1>(T1 argument, string message = null) where T1 : class, IEnumerable
{
if (argument == null)
{
throw new ArgumentNullException(message);
}
if(!argument.Any())
{
throw new ArgumentException(message);
}
return argument;
}
and use it like this for instance:
public void MyMethod(IList<double> stuff)
{
_stuff = NotEmpty(stuff);
....
}
but it doesn't compile. The extension method Any() seems to be defined only on the generic version of IEnumerable. However, I couldn't define the NotEmpty method such that the generic argument implements the generic version of IEnumerable and the compiler is able to work out the types automatically. The last thing I want is to type all the types manually.
Is it possible to implement it in a more elegant way than the one given below?
public static T1 NotEmpty<T1>(T1 argument, string message = null) where T1 : class, IEnumerable
{
if (argument == null)
{
throw new ArgumentNullException(message);
}
if(!argument.GetEnumerator().MoveNext())
{
throw new ArgumentException(message);
}
return argument;
}
You could Cast it so that you can use the LINQ extension methods.
Cast is an extension method for IEnumerable, while most other LINQ extension methods (such as Any) are only for IEnumerable<T>. Since using IEnumerable<T> would complicate your code (due to having two generic types involved), I'd probably go with this:
public static T1 NotEmpty<T1>(T1 argument, string message = null) where T1 : class, IEnumerable
{
if (argument == null)
{
throw new ArgumentNullException(message);
}
if(!argument.Cast<object>().Any())
{
throw new ArgumentException(message);
}
return argument;
}
just add an .OfType<Object>() to turn your non generic IEnumerable into something more useful:
public static T1 NotEmpty<T1>(T1 argument, string message = null) where T1 : class, IEnumerable
{
if (argument == null)
throw new ArgumentNullException(message);
if(!argument.OfType<Object>().Any())
throw new ArgumentException(message);
return argument;
}
Why use an Enumerable as generic type? It's about the type of the Enumerable:
public static IEnumerable<T1> NotEmpty<T1>(IEnumerable<T1> argument, string message = null) where T1 : class
{
if (argument == null)
{
throw new ArgumentNullException(message);
}
if(!argument.Any())
{
throw new ArgumentException(message);
}
return argument;
}
I want a static helper method to remove magic strings. Of course, I could pack the property method inside the TestContainer, which would remove the need to provide the TestContainer as argument. This is done nicely here.
But I would like to have the helper method in one static class, in case I later decide to optimize my code and remove the method. I managed to get it down to this, but its a little bit ugly (having to provide the string type, looks not very nice).
Any "expression god" knowing a better way. Keep in mind, the static class should be kept universal and not know anything about the TestContainer (otherwise it would be as easy as the link provided)
internal class PropertyNameResolving
{
internal class TestContainer
{
public string LastName { get; set; }
}
internal static class BindingHelper
{
public static string PropertyName<TObject, TValue>(Expression<Func<TObject, TValue>> propertySelector)
{
var memberExpression = propertySelector.Body as MemberExpression;
if (memberExpression != null) return memberExpression.Member.Name;
else
throw new Exception("Something went wrong");
}
}
internal static void Test()
{
var t = new TestContainer {LastName = "Hans"};
Console.WriteLine(BindingHelper.PropertyName<TestContainer, string>(x => x.LastName));
Console.ReadLine();
}
}
Btw, the output is "LastName" and can be used to set bindings.
And one more question, can I remove the NULL check safely?
3 options for you:
make the class generic, and use inference on the method for the value
use an example object for inference on the method
forget about the object type entirely and just use an example
These are all shown below. Re the null safety - I would be tempted to check the expression-type (you can also handle methods, btw) - some more code shown here.
using System;
using System.Linq.Expressions;
internal class TestContainer
{
public string LastName { get; set; }
}
static class Program
{
static void Main()
{
var t = new TestContainer {LastName = "Hans"};
string s1 = BindingHelper<TestContainer>
.PropertyName(x => x.LastName);
string s2 = BindingHelper.PropertyName(t, x => x.LastName);
string s3 = BindingHelper.PropertyName(() => t.LastName);
}
}
internal static class BindingHelper
{
public static string PropertyName<TObject, TValue>(TObject template,
Expression<Func<TObject, TValue>> propertySelector)
{
var memberExpression = propertySelector.Body as MemberExpression;
if (memberExpression != null) return memberExpression.Member.Name;
else
throw new Exception("Something went wrong");
}
public static string PropertyName<TValue>(
Expression<Func<TValue>> propertySelector)
{
var memberExpression = propertySelector.Body as MemberExpression;
if (memberExpression != null) return memberExpression.Member.Name;
else
throw new Exception("Something went wrong");
}
}
internal static class BindingHelper<TObject>
{
public static string PropertyName<TValue>(
Expression<Func<TObject, TValue>> propertySelector)
{
var memberExpression = propertySelector.Body as MemberExpression;
if (memberExpression != null) return memberExpression.Member.Name;
else
throw new Exception("Something went wrong");
}
}
Because the compiler can imply the type arguments, you shouldn't need to provide at all in the Test() method without changing anything.
Use BindingHelper.PropertyName(x => x.LastName) and it should work fine as is.
You can't remove the null check safely as your expression could be anything, include method call, which wouldn't count as a MemberExpression.