Help with a generics issue please?

I have the following class (includes relavent parts only). The first two methods work great, but the class also needs to contain additional TypeMappings, only of a different type than the container. I cannot figure out how to do this. I’ve left my code as-is, in a broken state so you can see what I’m thinking.

public class TypeMapping<T> : Mapping, ITypeMapping<T> where T : class
{
public TypeMapping() : base("Type") { }
public IAssociationMapping Association<P>(Expression<Func<T, P>> expression)
{
string member = ((MemberExpression)(expression.Body)).Member.Name;
IAssociationMapping mapping = new AssociationMapping().Member(member);
mappings.Add(mapping as IMapping);
return mapping;
}
public IColumnMapping Column<P>(Expression<Func<T, P>> expression)
{
string member = ((MemberExpression)(expression.Body)).Member.Name;
IColumnMapping mapping = new ColumnMapping().Member(member);
mappings.Add(mapping as IMapping);
return mapping;
}
public ITypeMapping<S> Type<S>()
{
ITypeMapping<S> mapping = new TypeMapping<S>().Name(typeof(S).FullName);
mappings.Add(mapping as IMapping);
return mapping;
}

can you explain it a little better…
S can only be of a given… type is that it?
Does it depend on T?

I’m designing a fluent like interface to help design linq to sql xml mapping files. So let’s say I have the classes Category and SubCategory. A SubCategory is a Category where ParentId is not null. I Need to be able to do the following:

ITypeMapping catMap = new TypeMapping<Category>();
// add association and columns like normal here
// also set the IsDiscriminator property

ITypeMapping subCatMap = catMap.Type<SubCategory>();
// then set the discriminator value

The problem is, the above is not working. It will return the object, but when I try the below on subCatMap, it fails (though it works on catMap).

subCatMap.Column(x => x.Extra)…and so on.

For some reason, the expressions passed in to Association() and Column() only work when applied to a top level object. The objects returned by the type factory method do not like them.

Have you read these:

http://martinfowler.com/dslwip/ImplementingDsls.html

http://martinfowler.com/dslwip/InternalOverview.html

NOTE: Original post text replaced!

The offending code seems to be what is listed below, along with the error.


using System;
using System.Linq.Expressions;
namespace Influence
{
    public class TypeMapping<T> : Mapping, ITypeMapping<T> where T : class
    {
        public TypeMapping() : base("Type") { }
        public IAssociationMapping Association<P>(Expression<Func<T, P>> expression)
        {
            string member = ((MemberExpression)(expression.Body)).Member.Name;
            IAssociationMapping mapping = new AssociationMapping().Member(member);
            mappings.Add(mapping as IMapping);
            return mapping;
        }
        public IColumnMapping Column<P>(Expression<Func<T, P>> expression)
        {
            string member = ((MemberExpression)(expression.Body)).Member.Name; 
            IColumnMapping mapping = new ColumnMapping().Member(member);
            mappings.Add(mapping as IMapping);
            return mapping;
        }
        public ITypeMapping<S> Type<S>()
        {
            ITypeMapping<S> mapping = new TypeMapping<S>();
            mappings.Add(mapping as IMapping);
            return mapping;
        }
        #region ITypeMapping<T> Members
        public ITypeMapping<T> InheritenceCode(string value)
        {
            return SetAttributeValue("InheritenceCode", value) as ITypeMapping<T>;
        }
        public ITypeMapping<T> IsInheritenceDefault(bool? value)
        {
            return SetAttributeValue("IsInheritenceDefault", value) as ITypeMapping<T>;
        }
        public ITypeMapping<T> Name(string value)
        {
            return SetAttributeValue("Name", value) as ITypeMapping<T>;
        }
        #endregion
    }
}

Error 1 The type ‘S’ must be a reference type in order to use it as parameter ‘T’ in the generic type or method ‘Influence.ITypeMapping<T>’ C:\…\ITypeMapping.cs 15 25 Influence

From this interface:


using System;
using System.Linq.Expressions;
using System.Xml.Linq;
namespace Influence
{
    public interface ITypeMapping<T> where T : class
    {
        IAssociationMapping Association<P>(Expression<Func<T, P>> expression);
        IColumnMapping Column<P>(Expression<Func<T, P>> expression);
        [COLOR=red]ITypeMapping<S> Type<S>();[/COLOR]
        ITypeMapping<T> InheritenceCode(string value);
        ITypeMapping<T> IsInheritenceDefault(bool? value);
        ITypeMapping<T> Name(string value);
    }
}

This is all I’m asking. How do I fix it? Where do I declare “where S : class”?

Sorry, thought you might like to learn how to write a Fluent Interface :stuck_out_tongue:

ITypeMapping<S> Type<S>() where S : class

Ah thanks!