Mirror, Mirror

18 10 2012

Urgh… spent the last 4 hours tangling and untangling code using reflection on assemblies in C# and I think I’ve gone cross-eyed 😛

I’ve managed to do what I set out to do, which is to load a few assemblies and get all the classes with a certain attribute to them. It isn’t terribly hard to do I agree but the confusing part comes when I figured I can’t, easily, unload those assemblies because of the whole separation by AppDomain and not being able to unload specific assemblies within a single AppDomain without unloading the entire domain. Using Assembly.LoadFrom, by the way, load the input assembly quite well but into the AppDomain.CurrentDomain (I’ve tried to unload that during a test just to see what would happen… it made me laugh).

So, the code itself is fairly simple; load the assembly, get all types from that assembly with the particular attribute and then query the attribute for the required information.

[Test]
public void can_retrieve_attribute_properties()
{
  var assembly = Assembly.LoadFrom(File);
  var types =
    (from type in assembly.GetTypes()
    where Attribute.IsDefined(type, typeof(ContentImporterAttribute))
    select type).ToList();

  var first = types[0];
  var customAttributes =
    (from attribute in first.GetCustomAttributes(true)
    where attribute is ContentImporterAttribute
    select (ContentImporterAttribute)attribute).ToList();

  var importerAttribute = customAttributes[0];
  Assert.IsTrue(importerAttribute.FileExtensions.Contains(".edi"));
  Assert.AreEqual("EDI Importer", importerAttribute.DisplayName);
  Assert.AreEqual("TestProcessor", importerAttribute.DefaultProcessor);
}

There are a few caveats there; the first and most obvious one is that the test implies there is somewhere another assembly that has that particular attribute attached to a class in a very specific way (and in fact there is, I’ve made it myself for this test). The other little worry here is the fact that I’ve got no bound checking or indeed any null-assertions on referencing the first item in each list (I’m basically assuming that the first type is the one I’m looking for and that the first attribute on it is the one I’m looking for as well). But for me the biggest unknown here is the assembly loading behavior in a real-world context (which I shall test later) in regards to the whole AppDomain merry-go-round; after going through MSDN and StackOverflow for a couple of hours I did find some solutions but I’m not sure that the complexity involved with creating specialized domains is worth the trouble.

Anyway, even if this approach fails (can anyone guess what I’m trying to do? :P) I’ve got another way to go about the system which would work for sure but it does mean a bit more manual labor.

“…I cut down trees, I eat my lunch I go to the lavatory…”

Advertisements




A Hard Link…

10 10 2012

… And no Zelda in sight!
Wow, I’ve sunk to new lows with my oh so wrong puns, but let’s move on.

I’m working with Unity again, who said that the sign of madness is to do the same thing over and over again and expect a different result? Well, unfortunately I’m expecting the same result, an easy starting slope which steeps up fairly quickly into a nerve-wrecking experience of Man vs. Machine. Unity by name only!

Anyway, my post is short since I actually have a deadline again, sort of.

One of the things that get me about Unity, and believe me there are many, is the fact I must see every goddamn file in the /Assets/ folder. That means that when I, like any sane person, circumvent the auto-generated Unity solution for my project, I have to put the .csproj files in the /Assets/ folder, not to mention the /bin/ and /obj/ folders and then get annoyed by them every time I open the folder in the project explorer. Aha! But no more! Surely you see where this is going, right? symbolic links for fun and, well, fun at the moment.

Nicely organized folders in five easy steps (I’ve actually just picked this number in random before writing the steps and I’m not going to edit it to make sure they match, so there 😛 ).

  1. Create Unity project.
  2. Create a new folder in the main Unity directory called Code or Source, or whatever rocks your boat.
  3. Create Solution file and add a new Unity.EditorScripts project.
  4. Go to /Assets/ and create /Assets/Code/Unity.EditorScripts.
  5. Create symbolic link in the actual project folder between it and the one in the /Assets/ folder (I called it code).
  6. Go play Cypher ’cause it rocks!

Blimey, it did actually take only five steps. And yes, Cypher is awesome. Go play it, now, I’ll wait… Actually I won’t but don’t let that bother you.

And just for a last little nibble. To make a link between folders simply:
mklink /d e:\Unity\AwesomeProject\Solution\ProjectName\Code e:\Unity\AwesomeProject\Assets\Code\ProjectName

Don’t forget the slash ‘d’ or it’ll make a file link (I had a couple of aborted attempts before realizing that).

Now all that’s left is to automate the process with Visual Studio, lose the annoying /Code/ ugliness in the project directory and I’m good to go.

“but blood makes noise”