0

I want to make a really generic class to save objects to a WCF service. I get an object of any type and analyse the objects properties via reflection. When saving the object into the service context, I need to know, if I have to call the SetLink(...) method of the DataServiceContext for a property or not.

Therefore I need a method to find out, if I have to call SetLink(...) or not. I already tried to doit by myself:

private bool IsLinkedProperty(PropertyInfo propertyInfo)
{
    return (propertyInfo != null) && propertyInfo.PropertyType.IsClass;
}

But this function does not work for string-properties and maybe for others too. Does anybody has a fitting function for this?

Oscar
  • 13,594
  • 8
  • 47
  • 75
scher
  • 1,813
  • 2
  • 18
  • 39
  • Can you define the criteria for determining whether the method should be called? – stuartd Mar 23 '16 at 11:05
  • You can find the `SetLink`method here: [link](https://msdn.microsoft.com/en-us/library/system.data.services.client.dataservicecontext.setlink%28v=vs.113%29.aspx). As I understand for all "primitive" data types. – scher Mar 23 '16 at 11:20
  • It looks to me like you will need to add metadata (ie attributes) to your properties to know when to call the method, and what to pass for the parameters. – stuartd Mar 23 '16 at 11:51

1 Answers1

0

I ended up with the following solution. I found a hint in the qestion of Nathan Ridley:

/// <summary>
/// Helper class for analyzing a type.
/// </summary>
public static class TypeAnalyzer
{
    /// <summary>
    /// Calculates if the given type is a "simple" type.
    /// </summary>
    /// <param name="type">Type to be checked for simplicity.</param>
    /// <returns>True, if the type is "simple";false otherwise.</returns>
    /// <remarks>
    ///   The following types are assumed to be simple:
    ///   <list type="*">
    ///     <item>string</item>
    ///     <item>int</item>
    ///     <item>decimal</item>
    ///     <item>float</item>
    ///     <item><see cref="StringComparison"/> (enum type)</item>
    ///     <item>int? (nullable simple types)</item> 
    ///   </list>
    ///   The following types are not simple:
    ///   <list type="*">
    ///     <item>Point (struct)</item>
    ///     <item>Point? (nullable struct)</item>
    ///     <item>StringBuilder (class)</item>
    ///   </list>
    /// </remarks>
    public static bool IsSimple(this Type type)
    {
        if (IsNullableType(type))
            return IsNestedTypeSimple(type);

        return type.IsPrimitive
          || type.IsEnum
          || type.Equals(typeof(string))
          || type.Equals(typeof(decimal))
          || type.Equals(typeof(DateTime))
          || type.Equals(typeof(Guid));
    }

    private static bool IsNestedTypeSimple(Type type)
    {
        var nestedType = Nullable.GetUnderlyingType(type);
        return IsSimple(nestedType);
    }

    private static bool IsNullableType(Type type)
    {
        return Nullable.GetUnderlyingType(type) != null;
    }
}

Test cases written in NUnit are:

[TestFixture]
public class TypeAnalyzerTests
{
    [TestCase(typeof(string), true)]
    [TestCase(typeof(int), true)]
    [TestCase(typeof(decimal), true)]
    [TestCase(typeof(float), true)]
    [TestCase(typeof(StringComparison), true)]
    [TestCase(typeof(int?), true)]
    [TestCase(typeof(decimal?), true)]
    [TestCase(typeof(StringComparison?), true)]
    [TestCase(typeof(object), false)]
    [TestCase(typeof(Point), false)]
    [TestCase(typeof(Point?), false)]
    [TestCase(typeof(StringBuilder), false)]
    [TestCase(typeof(DateTime), true)]
    [TestCase(typeof(Guid), true)]
    [TestCase(typeof(Guid?), true)]
    public void IsSimple_WhenCalledForType_ReturnsExpectedResult(Type type, bool expectedResult)
    {
        var isSimple = TypeAnalyzer.IsSimple(type);

        Assert.That(isSimple, Is.EqualTo(expectedResult));
    }
}

Finally I changed the in the question mentioned method to:

private bool IsLinkedProperty()
{ 
    return (_propertyInfo != null) && !_propertyInfo.PropertyType.IsSimple();
}
Community
  • 1
  • 1
scher
  • 1,813
  • 2
  • 18
  • 39