views:

143

answers:

1

I've run into an issue which I'm not sure if I can get round or not. My library and another library both provide an API for a particular type of data and I've now written an interop library that can sit between the two libraries and convert data freely between them which works great.

BUT I've now tried to write a small demo app of accessing data via my API using a third library which relies on the other API and here's where I hit issues. The third library references a merged version of the other API and some associated DLLs which to boot is an old version of the other API while my API references the latest version of the other API in it's standalone form. So to start with I have to use an external alias to even write code with the 3 libraries together as otherwise types clash and it won't compile.

So now when I try and write an app which takes data from my API, runs it through the interop layer so it's transformed into the other API and then uses the third library on this data things fall apart as .Net won't convert between the types as it considers them different. Is there any way to force .Net to do this or am I out of luck?

As I understand it the author of the third library plans to move his library to be based on the latest version (1.0.6.4) of the other API in the future so I may just have to wait until then?

using System;
using System.Collections.Generic;
using System.Linq;
using VDS.RDF;
using VDS.RDF.Interop;
using VDS.RDF.Parsing;
using VDS.RDF.Storage;
using SemWeb;
using LinqToRdf;

namespace RdfMusic
{
    public class Program
    {
        public static void Main(string[] args)
        {
            try
            {
                //Get the Talis Connection
                TalisPlatformConnector talis = new TalisPlatformConnector("store", "user", "password");
                NativeStoreSource source = new NativeStoreSource(talis);

                //Load the Data
                Graph g = new Graph();
                FileLoader.Load(g, "data.ttl");

                //Ensure the data is in Talis
                talis.SaveGraph(g);

                //Now do a LinqToRdf query
                //BUG: This cast fails since it's trying to cast to StatementSource in 
                //the SemWeb library (version 1.0.5.0 as referenced by LinqToRdf) from
                //a StatementSource in the SemWeb library (version 1.0.6.4 as referenced by dotNetRDF)
                StatementSource stmtSource = (StatementSource)source;
                LinqToRdf.TripleStore ts = new LinqToRdf.TripleStore(new Store(stmtSource));
                ts.QueryType = QueryType.LocalN3StoreInMemory;

                IEnumerable<Track> tracks = from t in new MusicDataContext(ts).ForType<Track>()
                                            where t.Year == "2006"
                                            select t;

                foreach (Track t in tracks)
                {
                    Console.Write(t.Title + " by " + t.ArtistName);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
                Exception innerEx = ex.InnerException;
                while (innerEx != null)
                {
                    Console.WriteLine();
                    Console.WriteLine(innerEx.Message);
                    Console.WriteLine(innerEx.StackTrace);
                    innerEx = innerEx.InnerException;
                }
            }

            Console.WriteLine();
            Console.WriteLine("Press Enter to exit");
            Console.ReadLine();
        }
    }
}
+1  A: 

Yes, you're out of luck. From CLR point of view, a type name is assembly name + optional module name + type name (this includes namespaces and outer classes), and the system is nominal, not structural - different name means different type. The best you can do is convert manually, insofar as you can given accessibility of members (or just work around it using reflection).

Pavel Minaev
Indeed. Note however that C# 4 will support a limited form of structural typing on *interfaces*. See http://blogs.msdn.com/samng/archive/2010/01/24/the-pain-of-deploying-primary-interop-assemblies.aspx for details.
Eric Lippert
@Eric, I've experimented with it, but from what I could see it's really hard to make C# compiler consume it - just sticking `TypeIdentifierAttribute` didn't cut it, it also wanted a bunch of COM Interop attributes (altogether they look like it tries to ensure that the assembly is the primary interop assembly). This was in VS2010 beta 2, though...
Pavel Minaev