XNA GS 3.1 and Scurvy.Media

So unless you’ve been living  under a rock (and/or don’t care about XNA :-P ), you obviously know that v3.1 was announced last week during the GDC.  Not a lot of info has really been put out there as far as specifics go, this seems to be one of the best sources so far:
http://blogs.msdn.com/astebner/archive/2009/03/24/9506368.aspx

    • Support for customized Avatars
    • Support for Xbox LIVE Party features
    • Video playback
    • Updated audio APIs for “fire-and-forget” scenarios
    • Support for XACT3
    • Automatic XNB serialization
    • XNA Framework multi-targeting in the Visual Studio 2008 and/or Visual C# 2008 Express Edition IDE
    • Downloadable content for Xbox LIVE Arcade titles that use XNA Game Studio 3.1
    • Consumer notifications when an Xbox LIVE Community Game that they have purchased has been updated

Of course, the video playback feature stood out for me, as it would seem that it will affect the Scurvy.Media project.  I’ve been getting some questions on the matter so I figured I’d just put my current thoughts out there.

Basically, I think it’s great :-) even if it ends up making the library completely obsolete.  I imagine that they will have ways around some of the roadblocks I encountered such as large filesize issues, and texture compression.  Depending on how their feature is factored, there *may* still be a place for Scurvy.Media … for example, I believe I read somewhere on the forums that it will only support WMV (don’t quote me on this, I may have misread or am not remembering right).  But if this is the case, and they’ve factored some level of extensibility into their API, then Scurvy.Media may add support for AVI videos.

In the end, I’m quite happy to see this and the other features coming out … looking forward to giving the beta a shot when it’s announced eventually :-D

Comments (2)

MapReduce in C# using LINQ

I recently remembered reading this article by Dare Obasanjo (Functional Programming in C# 3.0: How Map/Reduce/Filter can Rock your World) a long while ago, which was partly a response to Joel Spolsky’s article (Can Your Programming Language Do This).  In that article, Dare maps the map/reduce/filter functions to the following Linq equivalents:

  • map -> Enumerable.Select
  • reduce -> Enumerable.Aggregate
  • filter -> Enumerable.Where

At the time, I hadn’t really had a business need to play with Linq aside from casual curiosity … all of the projects at work were using other techniques for data access.  But more recently, we’ve been using linq more and more, and I experimented with how a rewrite of a feature might look if it had been written using a functional programming style with LINQ.

My experience with that reminded me of something I had read even longer ago, Google’s famous MapReduce paper (MapReduce: Simplified Data Processing on Large Clusters). Now, most of that paper deals with how they distribute the load across a large cluster of computers.  But near the very beginning, they have some small examples of the types of problems that could easily be solved by mapreduce, and even a sample pseudocode implementation of one of those programs.

map(String key, String value):
    // key: document name
    // value: document contents
    for each word w in value:
        EmitIntermediate(w, "1");

reduce(String key, Iterator values):
    // key: a word
    // values: a list of counts
    int result = 0;
    for each v in values:
        result += ParseInt(v);
    Emit(AsString(result));

Note the structure of the various inputs and outputs … in particular, the output of map (which serves as the input to reduce).  It’s a key along with an iterator of values that matched that key.  That sounds exactly like what GroupBy does.  Check out the description from this article:

The standard query operators also include the GroupBy operator, which imposes a partitioning over a sequence of values based on a key extraction function.

Using linq, I can implement the mapreduce program described above:

var wordOccurrences = words
                .GroupBy(w => w)
                .Select(intermediate => new
                {
                    Word = intermediate.Key,
                    Frequency = intermediate.Sum(w => 1)
                })
                .Where(w => w.Frequency > 10)
                .OrderBy(w => w.Frequency);

as you can see … based on google’s definition of MapReduce, I think that Dare was incorrect in asserting that select maps to map (no pun intended), and aggregate maps to reduce.  In this example, the GroupBy method is acting as the map, while the Select method does the job of reducing the intermediate results into the final list of results.

The obvious caveat here is that this isn’t distributed, it will run locally in memory.   But even without the massive scaling that google’s mapreduce data center can provide, it can be useful to think of problems in this mindset.  And when the parallel extensions for linq are finally released, you might even be able to easily take advantage of multiple cores.

Comments (3)

InstantRails: First Impression

So on a lark, I installed InstantRails last night to see what all the hubbub was about.  I grabbed the latest (v2.0) and set to following some getting started steps from a book. 

Unfortunately, it seems that things aren’t quite as easy as just downloading and getting started.  Just trying to start up a sample/demo site responded with a bunch of errors … so I ended up having to do a bunch of updates to the environment.  These are the commands I had to run to get to a point that I could run “rails demo”

gem update rails –include-depencies
gem install activerecord
gem install rake
gem install actionpack
gem install actionmailer
gem install activeresource
gem update –system

I mean, it was ultimately not too bad, but at the same time, not a great first impression.  So far, lots of the same concepts that I’ve gotten used to in ASP.NET MVC seem like they found their roots in RoR … so it’s good to see them in their original context.

Comments (1)

Converting a Lifecam VX-5000 to see IR

So I’ve recently become interested in building a multitouch table such as the one seen here.  All of the techniques for building them involve having a webcam that can see infrared, so I figured that was a first step.

The guys over at NUI Group have a great writeup and list of webcams that are easily modifiable for this purpose: http://wiki.nuigroup.com/Cameras

Despite that list, I ended up getting a Microsoft LifeCam VX-5000.  The first thing I did to test was put together the simple test rig described here (MT Mini).  Very ingenious to simply invert the webcam image so it looks like it’s just IR light.  That worked really well.

So I set about modifying the camera.  Since I couldn’t really find anything online about modifying this model, I decided to post the steps in case it helps anyone else.  Sadly, I neglected to take pictures during the process, so you’ll have to rely on my vivid descriptions :-P

  1. Remove the silver ring on the front of the camera.  It’s stuck on using a small amount of adhesive so you just kind of have to pry it off.
  2. Unscrew the two screws keeping the surrounding lens cover and remove it.
  3. Unscrew the 3 screws and remove the entire front face.  The live messenger button on top will also fall off once you remove it.
  4. Unscrew the lens, it had a small amount of some sort of adhesive, which I just had to scratch off with a knife.
  5. Remove the screws from the circuit board and remove it from the bottom casing.
  6. Unscrew the additional lens housing from the bottom of the board.  This is what’s covering the IR filter.
  7. Once you remove that, you’ll have to remove the IR filter (it looks like it reflects redish light).  It was glued on so I ended up having to kind of crack the ir filter to remove it piece by piece.
  8. Install the IR-Pass filter … of course, this is where everyone seems to hack it, since lots of guides online tend to suggest using exposed film negative.  I cut out two pieces and put them in place of the IR filter.
  9. With that done, rebuild everything you’ve just taken apart until the camera is put back together.

I used the TBeta from NUI Group for testing: http://tbeta.nuigroup.com/

And it worked pretty well … I was able to get a remote control and use it to track the IR LED that lights up when you press a button.  The next step will be to start building the FTIR surface.  Stay tuned :-P

Comments (2)

ONETUG XNA Presentation Files

As promised, here are the presentation files from the ONETUG presentation the other night.

http://codecube.net/bloguploads/ONETUG_XNA_20090129.zip

The .zip contains both the powerpoint slides that I used in the presentation, and the two sample projects I developed during the presentation.

  • TwoD
    • This sample shows some basic 2D techniques for dealing with sprites on the screen.
    • Simple velocity calculations for locomotion (Position += Velocity)
    • Orbiting one sprite around another
    • Launching projectiles at a steady pace.
    • Sprite helper class that makes it easy to position sprites around the world.
    • I didn’t use it in the sample, but I also have a ResourcePool datatype that makes it easy to reuse entities without having to reallocate new memory.  This is actually a really useful technique, I’d like to write about it in a separate blog post.
  • ThreeD
    • First Person Shooter style Camera.  It’s a GameComponent, so you just have to add it to the Components collection to use it.
    • Used the QuadDrawer class from the 3D Audio sample.  I added a few useful overloads and methods to let you draw billboarded sprites and the floor.
    • ModelSprite that makes drawing sprites and positioning it about the world easy.
    • Used the Sky box processor from the Generated Geometry sample.
    • All the helper classes (QuadDrawer, ModelSprite, and Sky) all know the camera, so they can make use of its view and projection matrix.

Thanks to everyone who showed up :-)

Comments

Scurvy.Media Now Supports XNA GS 3.0

well, it was a long time coming … my apologies to those who were waiting for this :-) but I finally got around to releasing a version of Scurvy.Media that was compiled against XNA 3.0

You can find the latest download here: http://www.codeplex.com/ScurvyMedia

There aren’t any new features … the reason this got caught up in the first place is because I was trying to have zune support in before I released it and then I got busy.  Oh well, c’est la vie … I still have to work out the specific surface format and data format that will work on the zune.  I think I’m close …

Please let me know if you encounter any issues with this version :-) thanks!

Comments (1)

It’s almost that time of year

More often than not, I hear about people who think so low of their ability to keep new years resolutions, that they refuse to make them.  However, I think that a periodic reflection of your life, your goals, and your priorities is important.  And thus, I will be making my list, and checking it twice next week :-)

Merry Christmas to everyone

Comments

Using the LateBinder

Heh, I seemed to have not realized that I didn’t include any usage information on the LateBinder in the last post.  So here is the how and why you’d want to use this class.

Say you have a need to dynamically get or set the property of some class using the string name of the property.  Normally, the answer would be to use reflection, get the PropertyInfo, extract the MethodInfo of the getter or setter, and then invoke that method using the reflection API.  Hardly very usable … and if you’re not careful, you will end up paying the reflection cost everytime because you have to keep looking up the PropertyInfo and all that.

Enter the LateBinder<T> … using this class, you can do:

MyClass mcInstance = new MyClass();

LateBinder<MyClass> binder = LateBinder<MyClass>.Instance;
binder[mcInstance, "Name"] = “my name”;
string name = (string)binder[mcInstance, "Name"];

The late binder (on windows) uses the System.Reflection.Emit API to generate a DynamicMethod, which is much faster to call than the reflection invoke because it’s pre-compiled using custom built IL instructions.  It also caches them in the late binder instance so that it only has to be compiled once … and furthermore, if you use the singleton .Instance method, you only have to do the compilation once per application run since it keeps the data around in a static variable.

Beneath the hood, the original version of the late binder was using this class.  But I had to change the design of the class to support the cross platform aspect of it and to add in the static support.  It was pretty fun, I ended up using reflector to decompile some sample code I wrote in a console app so I could see what IL instructions I had to use to get/set the statics … so with this version of LateBinder, it supports getting and setting both properties and fields … regardless of whether they are instance or static fields/properties.

Now, on XBox and Zune, the story changes a bit because System.Reflection.Emit does not exist.  So, in this new version I posted, it falls back to simply using reflection.  However, it does keep the propertyinfo in that static cache, so at least you won’t have to pay the penalty of looking for it every time.

So to get back to the original question on usage (ie. when/why would I want to use it) … it probably wouldn’t be a good idea to use this in a tight loop in runtime code.  However, for certain tools and custom serialization code … it could certainly be very useful.  For example, you can relatively easily write code using this that will transfer property values from one class to another … assuming the property names are the same.  The list goes on and on as to how this is useful.

Comments (2)

New LateBinder

A long time ago, I posted a class called LateBinder to this site (the previous blog software).  I went on to use it rather prodigiously at work, and it also turned out to be a boon to others who visited this site (for example, Victor of FlatRedBall fame).  Unfortunately, it did have a few limitations; namely that it didn’t support getting/setting static fields and properties, and it also didn’t work on the xbox360 and zune because the System.Reflection.Emit namespace wasn’t available.

He asked me the other day the feasibility of supporting the static properties, and after a few days of hacking about, I’ve added that, and then some :-)

The version (below) not only supports static fields and properties, but it also supports the xbox360 and zune platforms.  Be warned though, I had to fall back on using simple reflection on the non-windows platforms … so the perf will obviously be slightly slower. 

I am fairly proud of how I was able to refactor the code to encapsulate the cross-platform differences.  If you look at the LateBindFactory abstract class, it uses a factory method to instantiate the platform-specific version.  This way, I was able to keep the pre-processor directives to a minimum, using them only where I needed … and also keeping the same public API for both platforms.

Let me know if this is useful for you  :-)

#region Using Statements

#if !XBOX360 && !ZUNE
#define USE_EMIT
#endif

using System;
using System.Collections.Generic;
using System.Reflection;
#if USE_EMIT
using System.Reflection.Emit;
#endif

#endregion

namespace Scurvy
{
    /// <summary>
    /// Provides a simple interface to late bind a class.
    /// </summary>
    /// <remarks>The first time you attempt to get or set a property, it will dynamically generate the get and/or set
    /// methods and cache them internally.  Subsequent gets uses the dynamic methods without having to query the type’s
    /// meta data.</remarks>
    public sealed class LateBinder<T>
    {
        #region Fields

        private static LateBindFactory factory = LateBindFactory.Create();
        private BindingFlags propertyFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static;
        private Type mType;
        private Dictionary<string, GetHandler> mPropertyGet;
        private Dictionary<string, SetHandler> mPropertySet;

        private Dictionary<Type, List<string>> mFields;

        private T mTarget = default(T);

        private static LateBinder<T> _instance;

        #endregion

        #region Properties

        public static LateBinder<T> Instance
        {
            get { return _instance; }
        }

        /// <summary>
        /// The instance that this binder operates on by default
        /// </summary>
        /// <remarks>This can be overridden by the caller explicitly passing a target to the indexer</remarks>
        public T Target
        {
            get { return mTarget; }
            set { mTarget = value; }
        }

        /// <summary>
        /// Gets or Sets the supplied property on the contained <seealso cref=”Instance”/>
        /// </summary>
        /// <exception cref=”InvalidOperationException”>Throws if the contained Instance is null.</exception>
        public object this[string propertyName]
        {
            get
            {
                //ValidateInstance();
                return this[mTarget, propertyName];
            }
            set
            {
                //ValidateInstance();
                this[mTarget, propertyName] = value;
            }
        }

        /// <summary>
        /// Gets or Sets the supplied property on the supplied target
        /// </summary>
        public object this[T target, string propertyName]
        {
            get
            {
                ValidateGetter(ref propertyName);
                return mPropertyGet[propertyName](target);
            }
            set
            {
                ValidateSetter(ref propertyName);
                mPropertySet[propertyName](target, value);
            }
        }

        #endregion

        #region Methods

        #region Constructors

        static LateBinder()
        {
            _instance = new LateBinder<T>();
        }

        public LateBinder(T instance)
            : this()
        {
            mTarget = instance;
        }

        public LateBinder()
        {
            mType = typeof(T);
            mPropertyGet = new Dictionary<string, GetHandler>();
            mPropertySet = new Dictionary<string, SetHandler>();

            mFields = new Dictionary<Type, List<string>>();
        }
        #endregion

        #endregion

        #region Public Accessors

        /// <summary>
        /// Sets the supplied property on the supplied target
        /// </summary>
        /// <typeparam name=”K”>the type of the value</typeparam>
        public void SetProperty<K>(T target, string propertyName, K value)
        {
#if !USE_EMIT

            // find out if this is a property or field
            Type type = typeof(T);

            PropertyInfo propertyInfo = type.GetProperty(propertyName);

            if (propertyInfo != null)
            {
                propertyInfo.SetValue(target, value, null);
            }

            else
            {
                FieldInfo fieldInfo = type.GetField(propertyName);

                if (fieldInfo != null)
                {
                    fieldInfo.SetValue(target, value);
                }
                else
                {
                    throw new ArgumentException(“Cannot find property or field with the name ” + propertyName);
                }

            }

#else
            ValidateSetter(ref propertyName);

            if (mPropertySet.ContainsKey(propertyName))
            {
                mPropertySet[propertyName](target, value);
            }
            else
            {
                // This is probably not a property so see if it is a field.

                FieldInfo fieldInfo = mType.GetField(propertyName);

                if (fieldInfo == null)
                {
                    string errorMessage =
                        “LateBinder could not find a field or property by the name of ” + propertyName +
                        “Check the name of the property to verify if it is correct.”;
                    throw new System.MemberAccessException(errorMessage);
                }
                else
                {
                    object[] args = { value };
                    mType.InvokeMember(propertyName, BindingFlags.SetField, null, target, args);
                }
            }
#endif
        }

        public object GetField(T target, ref string propertyName)
        {
            Binder binder = null;
            object[] args = null;

            return mType.InvokeMember(
               propertyName,
               BindingFlags.GetField,
               binder,
               target,
               args
               );
        }

        /// <summary>
        /// Gets  the supplied property on the supplied target
        /// </summary>
        /// <typeparam name=”K”>The type of the property being returned</typeparam>
        public K GetProperty<K>(T target, ref string propertyName)
        {
            ValidateGetter(ref propertyName);
            return (K)mPropertyGet[propertyName](target);
        }

        public object GetProperty(T target, ref string propertyName)
        {
            ValidateGetter(ref propertyName);
            return mPropertyGet[propertyName](target);
        }

        #endregion

        #region Private Helpers

        private void ValidateInstance()
        {
            if (mTarget == null)
            {
                throw new InvalidOperationException(“Instance property must not be null”);
            }
        }

        private void ValidateSetter(ref string propertyName)
        {
            if (!mPropertySet.ContainsKey(propertyName))
            {
                PropertyInfo propertyInfo = mType.GetProperty(propertyName, this.propertyFlags);

                if (propertyInfo != null)
                {
                    mPropertySet.Add(propertyName, factory.CreateSetHandler(mType, propertyInfo));
                }
            }
        }

        private void ValidateGetter(ref string propertyName)
        {
            if (!mPropertyGet.ContainsKey(propertyName))
            {
                mPropertyGet.Add(propertyName, factory.CreateGetHandler(mType, mType.GetProperty(propertyName)));
            }
        }

        #endregion

        #region Contained Classes

        internal delegate object GetHandler(object source);
        internal delegate void SetHandler(object source, object value);
        internal delegate object InstantiateObjectHandler();

        internal abstract class LateBindFactory
        {
            public LateBindFactory()
            {
            }

            public static LateBindFactory Create()
            {
#if USE_EMIT
                return new DynamicMethodFactory();
#else
                return new ReflectionFactory();
#endif
            }

            public abstract InstantiateObjectHandler CreateInstantiateObjectHandler(Type type);
            public abstract GetHandler CreateGetHandler(Type type, PropertyInfo propertyInfo);
            public abstract GetHandler CreateGetHandler(Type type, FieldInfo fieldInfo);
            public abstract SetHandler CreateSetHandler(Type type, PropertyInfo propertyInfo);
            public abstract SetHandler CreateSetHandler(Type type, FieldInfo fieldInfo);
        }

#if USE_EMIT
        internal sealed class DynamicMethodFactory : LateBindFactory
        {
            public DynamicMethodFactory()
            {
            }

            #region Public Methods

            public override InstantiateObjectHandler CreateInstantiateObjectHandler(Type type)
            {
                ConstructorInfo constructorInfo = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[0], null);
                if (constructorInfo == null)
                {
                    throw new ApplicationException(string.Format(“The type {0} must declare an empty constructor (the constructor may be private, internal, protected, protected internal, or public).”, type));
                }

                DynamicMethod dynamicMethod = new DynamicMethod(“InstantiateObject”, MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, typeof(object), null, type, true);
                ILGenerator generator = dynamicMethod.GetILGenerator();
                generator.Emit(OpCodes.Newobj, constructorInfo);
                generator.Emit(OpCodes.Ret);
                return (InstantiateObjectHandler)dynamicMethod.CreateDelegate(typeof(InstantiateObjectHandler));
            }

            public override GetHandler CreateGetHandler(Type type, PropertyInfo propertyInfo)
            {
                MethodInfo getMethodInfo = propertyInfo.GetGetMethod(true);

                DynamicMethod dynamicGet = CreateGetDynamicMethod(type);
                ILGenerator getGenerator = dynamicGet.GetILGenerator();

                if (!getMethodInfo.IsStatic)
                {
                    getGenerator.Emit(OpCodes.Ldarg_0);
                }
                getGenerator.Emit(OpCodes.Call, getMethodInfo);
                BoxIfNeeded(getMethodInfo.ReturnType, getGenerator);
                getGenerator.Emit(OpCodes.Ret);

                return (GetHandler)dynamicGet.CreateDelegate(typeof(GetHandler));
            }

            public override GetHandler CreateGetHandler(Type type, FieldInfo fieldInfo)
            {

                DynamicMethod dynamicGet = CreateGetDynamicMethod(type);
                ILGenerator getGenerator = dynamicGet.GetILGenerator();

                if (!fieldInfo.IsStatic)
                {
                    getGenerator.Emit(OpCodes.Ldarg_0);
                }
                getGenerator.Emit(OpCodes.Ldfld, fieldInfo);
                BoxIfNeeded(fieldInfo.FieldType, getGenerator);
                getGenerator.Emit(OpCodes.Ret);

                return (GetHandler)dynamicGet.CreateDelegate(typeof(GetHandler));
            }

            public override SetHandler CreateSetHandler(Type type, PropertyInfo propertyInfo)
            {
                MethodInfo setMethodInfo = propertyInfo.GetSetMethod(true);

                DynamicMethod dynamicSet = CreateSetDynamicMethod(type);
                ILGenerator setGenerator = dynamicSet.GetILGenerator();

                if (!setMethodInfo.IsStatic)
                {
                    setGenerator.Emit(OpCodes.Ldarg_0);
                }
                setGenerator.Emit(OpCodes.Ldarg_1);
                UnboxIfNeeded(setMethodInfo.GetParameters()[0].ParameterType, setGenerator);
                setGenerator.Emit(OpCodes.Call, setMethodInfo);
                setGenerator.Emit(OpCodes.Ret);

                return (SetHandler)dynamicSet.CreateDelegate(typeof(SetHandler));
            }

            public override SetHandler CreateSetHandler(Type type, FieldInfo fieldInfo)
            {
                DynamicMethod dynamicSet = CreateSetDynamicMethod(type);
                ILGenerator setGenerator = dynamicSet.GetILGenerator();

                if (!fieldInfo.IsStatic)
                {
                    setGenerator.Emit(OpCodes.Ldarg_0);
                }
                setGenerator.Emit(OpCodes.Ldarg_1);
                UnboxIfNeeded(fieldInfo.FieldType, setGenerator);

                if (!fieldInfo.IsStatic)
                {
                    setGenerator.Emit(OpCodes.Stfld, fieldInfo);
                }
                else
                {
                    setGenerator.Emit(OpCodes.Stsfld, fieldInfo);
                }

                setGenerator.Emit(OpCodes.Ret);

                return (SetHandler)dynamicSet.CreateDelegate(typeof(SetHandler));
            }

            #endregion

            #region Private Methods

            private static DynamicMethod CreateGetDynamicMethod(Type type)
            {
                return new DynamicMethod(“DynamicGet”, typeof(object), new Type[] { typeof(object) }, type, true);
            }

            // CreateSetDynamicMethod
            private static DynamicMethod CreateSetDynamicMethod(Type type)
            {
                return new DynamicMethod(“DynamicSet”, typeof(void), new Type[] { typeof(object), typeof(object) }, type, true);
            }

            // BoxIfNeeded
            private static void BoxIfNeeded(Type type, ILGenerator generator)
            {
                if (type.IsValueType)
                {
                    generator.Emit(OpCodes.Box, type);
                }
            }

            // UnboxIfNeeded
            private static void UnboxIfNeeded(Type type, ILGenerator generator)
            {
                if (type.IsValueType)
                {
                    generator.Emit(OpCodes.Unbox_Any, type);
                }
            }

            #endregion
        }
#endif

#if !USE_EMIT
        internal sealed class ReflectionFactory : LateBindFactory
        {
            public ReflectionFactory()
            {
            }

            public override InstantiateObjectHandler CreateInstantiateObjectHandler(Type type)
            {
                return delegate()
                {
                    return Activator.CreateInstance(type);
                };
            }

            public override GetHandler CreateGetHandler(Type type, PropertyInfo propertyInfo)
            {
                MethodInfo method = propertyInfo.GetGetMethod(true);

                return delegate(object source)
                {
                    return method.Invoke(method.IsStatic ? null : source, null);
                };
            }

            public override GetHandler CreateGetHandler(Type type, FieldInfo fieldInfo)
            {
                return delegate(object source)
                {
                    return fieldInfo.GetValue(fieldInfo.IsStatic ? null : source);
                };
            }

            public override SetHandler CreateSetHandler(Type type, PropertyInfo propertyInfo)
            {
                MethodInfo method = propertyInfo.GetSetMethod();

                return delegate(object source, object value)
                {
                    method.Invoke(method.IsStatic ? null : source, new object[] { value });
                };
            }

            public override SetHandler CreateSetHandler(Type type, FieldInfo fieldInfo)
            {
                return delegate(object source, object value)
                {
                    fieldInfo.SetValue(fieldInfo.IsStatic ? null : source, value);
                };
            }
        }
#endif
        #endregion
    }
}

Comments

Handy LinQ Extension Methods

Isn’t it annoying how an IEnumerable<SomeClassThatImplementsISomeInterface>, is not castable to IEnumerable<ISomeInterface> ?  The reasoning for this makes sense once you get into it … because of generics, those two are functionally different classes.

So, I made a handy-dandy extension method that does the job for me (at the cost of a few more allocations on the heap)

public static IEnumerable<KTo> Convert<TFrom, KTo>(this IEnumerable<TFrom> enumerable)
    where TFrom : KTo
{           
    return enumerable.Select((TFrom s) => (KTo)s);
}

The usage is very simple: return list.Convert<SomeClassThatImplementsISomeInterface, ISomeInterface>();

If you need to do this with an Entity Framework query, where your entities are partial classed to implement an interface … you need to use this version though:

public static IEnumerable<KTo> ConvertToList<TFrom, KTo>(this IEnumerable<TFrom> enumerable)
    where TFrom : KTo
{           
    return enumerable.ToList().Select((TFrom s) => (KTo)s);
}

note the .ToList() that’s injected in there … the reason for this is that the enumerable needs to be fully enumerated so that the EF executes the query and moves all the results into memory, before doing the cast in the select.

hope that helps :-)

Comments (3)