I was recently working on a WPF MVVM application that used MEF to load plugins. I had broken up the main WPF application into smaller more manageable compartmentalized projects to help ensure more cross platform code. But when I tried to run the program it would start up fine but as soon as it tried to utilize logic from my plugins I was getting "assembly or one of it’s dependencies not found" exceptions.

Main Application
    -> LibraryA (References to Xceed.WPF.Toolkit)

Turns out when visual studio compiled my solution it was not copying Xceed.Wpf.Tookit into the main application bin/Debug folder. To solve this took a lot of searching on the interwebz before coming across this handy solution. Recursively Copying Indirect Project Dependencies in MSBuild.

Just download the CopyIndirectDependencies.targets CopyIndirectDependencies.targets (9.19 kb) and put it in your main application folder. Then edit your projects .csproj file to include this line "<Import Project="CopyIndirectDependencies.targets" />"

 

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  ...

  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <Import Project="CopyIndirectDependencies.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>

Now when you build your main application project it should scan for indirect dependancies and copy them to the projects bin/Debug folder.


Full repo available at https://bitbucket.org/createdbyx/codefarts.utilities-extension-methods-only

/// <summary>Determines whether a value in within a certain range.</summary>
/// <param name="value">The value.</param>
/// <param name="min">The minimum value.</param>
/// <param name="max">The maximum value.</param>
/// <returns>True if the value is in range.</returns>
public static bool IsInRange(this BaseType value, BaseType min, BaseType max)
{
    return value >= min && value <= max;
}

/// <summary>Determines whether a value in within a certain range.</summary>
/// <param name="value">The value.</param>
/// <param name="min">The minimum value.</param>
/// <param name="max">The maximum value.</param>
/// <param name="throwException">if set to <c>true</c> will throw a <see cref="IndexOutOfRangeException"/> if the value is out of range.</param>
/// <returns>True if the value is in range.</returns>
/// <exception cref="System.IndexOutOfRangeException">Is thrown if the value is out of range.</exception>
public static bool IsInRange(this BaseType value, BaseType min, BaseType max, bool throwException)
{
    if (!(value >= min && value <= max) && throwException)
    {
        throw new IndexOutOfRangeException();
    }

    return true;
}

/// <summary>Determines whether a value in within a certain range.</summary>
/// <param name="value">The value.</param>
/// <param name="min">The minimum value.</param>
/// <param name="max">The maximum value.</param>
/// <param name="throwException">if set to <c>true</c> will throw a <see cref="IndexOutOfRangeException"/> if the value is out of range.</param>
/// <param name="message">The message for the <see cref="IndexOutOfRangeException"/> if it is thrown.</param>
/// <returns>True if the value is in range.</returns>
/// <exception cref="System.IndexOutOfRangeException">Is thrown if the value is out of range.</exception>
public static bool IsInRange(this BaseType value, BaseType min, BaseType max, bool throwException, string message)
{
    if (!(value >= min && value <= max) && throwException)
    {
        throw new IndexOutOfRangeException(message);
    }

    return true;
}

Full repo available at https://bitbucket.org/createdbyx/codefarts.utilities-extension-methods-only

/// <summary>
/// Clamps the specified value.
/// </summary>
/// <param name="value">The value to be clamped.</param>
/// <param name="min">The minimum value.</param>
/// <param name="max">The maximum value.</param>
/// <returns>The clamped value.</returns>
public static BaseType Clamp(this BaseType value, BaseType min, BaseType max)
{
    if (value < min)
    {
        return min;
    }

    if (value > max)
    {
        return max;
    }

    return value;
}

Full repo available at https://bitbucket.org/createdbyx/codefarts.utilities-extension-methods-only

/// <summary>
/// Determines weather or not all the characters in a string are all the same.
/// </summary>
/// <param name="value">The value to check for.</param>
/// <returns>true is all characters are the same, otherwise false.</returns>
public static bool AllTheSame(this string value)
{
#if UNITY3D
    if (!StringExtensionMethods.IsNullOrWhiteSpace(value))
#else
    if (!string.IsNullOrWhiteSpace(value))
#endif
    {
        var clone = new string(value[0], value.Length);
        return clone == value;
    }

    return false;
}

#if UNITY3D
public static bool IsNullOrWhiteSpace(this string value)
{
    if (value == null)
    {
        return true;
    }

    for (var i = 0; i < value.Length; i++)
    {
        if (!char.IsWhiteSpace(value[i]))
        {
            return false;
        }
    }

    return true;
}
#endif
}

Full repo available at https://bitbucket.org/createdbyx/codefarts.utilities-extension-methods-only

namespace System.Collections
{
    /// <summary>
    /// Provides extension methods for the IList interface.
    /// </summary>
    public static class IListExtensionMethods
    {
        /// <summary>Swaps the specified items in a list.</summary>
        /// <param name="list">The list.</param>
        /// <param name="indexA">The index of item A.</param>
        /// <param name="indexB">The index of item B.</param>
        /// <param name="remove">If set to <c>true</c> items will be removed and re-inserted.</param>
        public static void Swap(this IList list, int indexA, int indexB, bool remove)
        {
            if (indexA == indexB)
            {
                return;
            }

            indexA.IsInRange(0, list.Count - 1, true, "indexA is out of range.");
            indexB.IsInRange(0, list.Count - 1, true, "indexB is out of range.");

            if (remove)
            {
                var first = Math.Min(indexA, indexB);
                var second = Math.Max(indexA, indexB);
                
                var tempA = list[first];
                var tempB = list[second];

                list.RemoveAt(second);
                list.RemoveAt(first);
               
                list.Insert(first, tempB);
                list.Insert(second, tempA);
            }
            else
            {
                var temp = list[indexA];
                list[indexA] = list[indexB];
                list[indexB] = temp;
            }
        }

        /// <summary>Swaps the specified items in a list.</summary>
        /// <param name="list">The list.</param>
        /// <param name="indexA">The index of item A.</param>
        /// <param name="indexB">The index of item B.</param>
        /// <remarks>Items are swapped and not removed or inserted.</remarks>
        public static void Swap(this IList list, int indexA, int indexB)
        {
            Swap(list, indexA, indexB, false);
        }

        /// <summary>Swaps the specified items in a list and return true if successful.</summary>
        /// <param name="list">The list.</param>
        /// <param name="indexA">The index of item A.</param>
        /// <param name="indexB">The index of item B.</param>
        /// <remarks>Items are swapped and not removed or inserted.</remarks>
        /// <returns>true if successful.</returns>
        public static bool TrySwap(this IList list, int indexA, int indexB)
        {
            try
            {
                Swap(list, indexA, indexB);
            }
            catch
            {
                return false;
            }

            return true;
        }

        /// <summary>Swaps the specified items in a list and return true if successful.</summary>
        /// <param name="list">The list.</param>
        /// <param name="indexA">The index of item A.</param>
        /// <param name="indexB">The index of item B.</param>
        /// <param name="remove">If set to <c>true</c> items will be removes and re-inserted.</param>
        /// <returns>true if successful.</returns>
        public static bool TrySwap(this IList list, int indexA, int indexB, bool remove)
        {
            try
            {
                Swap(list, indexA, indexB, remove);
            }
            catch
            {
                return false;
            }

            return true;
        }
    }
}

Full repo available at https://bitbucket.org/createdbyx/codefarts.utilities-extension-methods-only

/// <summary>
/// Removes a range of entries inside an array.
/// </summary>
/// <typeparam name="T">Specifies the generic type of the array.</typeparam>
/// <param name="array">The destination array.</param>
/// <param name="index">The start index where entries will be removed from.</param>
/// <param name="length">The number of entries to be removed.</param>
/// <returns>
/// Returns the resized and updated destination array.
/// </returns>
/// <exception cref="ArgumentOutOfRangeException">index</exception>
public static T[] RemoveRange<T>(this T[] array, int index, int length)
{
    if (length < 1)
    {
        return array;
    }

    if (index < 0 || index > array.Length - 1)
    {
        throw new ArgumentOutOfRangeException("index");
    }

    if (index + length > array.Length - 1)
    {
        Array.Resize(ref array, index);
        return array;
    }

    var endLength = Math.Max(0, Math.Min(array.Length - index, array.Length - (index + length)));
    var tempArray = new T[endLength];
    Array.Copy(array, index + length, tempArray, 0, endLength);
    Array.Resize(ref array, array.Length - length);
    tempArray.CopyTo(array, array.Length - endLength);
    return array;
}

Full repo available at https://bitbucket.org/createdbyx/codefarts.utilities-extension-methods-only

/// <summary>
/// Moves the specified entries in the array by a set ammount.
/// </summary>
/// <typeparam name="T">Specifies the generic type of the array.</typeparam>
/// <param name="array">The destination array.</param>
/// <param name="index">The start index where entries will be moved from.</param>
/// <param name="length">The number of entries to be moved.</param>
/// <param name="shift">The ammount and direction to move the specified entries.</param>
/// <returns>
/// Returns the resized and updated destination array.
/// </returns>
/// <exception cref="ArgumentOutOfRangeException">length;'length' argument must be greater then 0.</exception>
/// <remarks><p>To move entries to the left (towards 0) specify a negative shift value and a positive shift value to move entries to the right.</p>
/// <example>
/// <code>
/// var items = new[] { 0, 1, 2, 3, 4 };
/// items = items.Move(3, 2, -1);
/// </code>
/// Result should be { 0, 1, 3, 4, 4 }
/// </example></remarks>
public static T[] Move<T>(this T[] array, int index, int length, int shift)
{
    if (length <= 0)
    {
        throw new ArgumentOutOfRangeException("length", "'length' argument must be greater then 0.");
    }

    if (shift > 0 && index + length + shift > array.Length - 1)
    {
        Array.Resize(ref array, array.Length + (index + length + shift - array.Length));
    }

    if (index + shift < 0)
    {
        length += index + shift;
        index = -(index + shift);
    }

    length = Math.Min(array.Length - index, length);
    if (length > 0)
    {
        Array.Copy(array, index, array, index + shift, length);
    }        

    return array;
}

Full repo available at https://bitbucket.org/createdbyx/codefarts.utilities-extension-methods-only

/// <summary>
/// Crops an array to a specified length.
/// </summary>
/// <typeparam name="T">Specifies the generic type of the array.</typeparam>
/// <param name="array">The destination array.</param>
/// <param name="length">The length that the destination array will be set to.</param>
/// <returns>Returns the resized and updated destination array.</returns>
public static T[] Crop<T>(this T[] array, int length)
{
    if (array == null)
    {
        return array;
    }

    Array.Resize(ref array, Math.Max(length, 0));
    return array;
}

/// <summary>
/// Crops an array to a specified length.
/// </summary>
/// <typeparam name="T">Specifies the generic type of the array.</typeparam>
/// <param name="array">The destination array.</param>
/// <param name="index">The index in the destination array where cropping begins at.</param>
/// <param name="length">The length that the destination array will be set to.</param>
/// <returns>
/// Returns the resized and updated destination array.
/// </returns>
/// <exception cref="ArgumentOutOfRangeException">length;'length' argument must be greater then 0.</exception>
public static T[] Crop<T>(this T[] array, int index, int length)
{
    if (array == null)
    {
        return array;
    }

    if (length <= 0)
    {
        throw new ArgumentOutOfRangeException("length", "'length' argument must be greater then 0.");
    }
                 
    if (index < 0 || index > array.Length - 1)
    {
        return array;
    }
                        
    length = Math.Min(length, array.Length - index);
    if (index > 0)
    {
        Array.Copy(array, index, array, 0, length);
    }

    Array.Resize(ref array, length);
    return array;
}

Full repo available at https://bitbucket.org/createdbyx/codefarts.utilities-extension-methods-only

/// <summary>
/// Adds the specified source array to the end of the destination array.
/// </summary>
/// <typeparam name="T">Specifies the generic type of the array.</typeparam>
/// <param name="array">The destination array.</param>
/// <param name="sourceArray">The source array that will be added to the end of the destination array.</param>
/// <returns>Returns the resized and updated destination array.</returns>
public static T[] Add<T>(this T[] array, T[] sourceArray)
{
    if (array == null || sourceArray == null || sourceArray.Length == 0)
    {
        return array;
    }

    Array.Resize(ref array, array.Length + sourceArray.Length);
    sourceArray.CopyTo(array, array.Length - sourceArray.Length);
    return array;
}

/// <summary>
/// Adds a new extry to the end of the destination array.
/// </summary>
/// <typeparam name="T">Specifies the generic type of the array.</typeparam>
/// <param name="array">The destination array.</param>
/// <param name="value">The item that will be added to the end of the destination array.</param>
/// <returns>Returns the resized and updated destination array.</returns>
public static T[] Add<T>(this T[] array, T value)
{
    if (array == null)
    {
        return array;
    }

    Array.Resize(ref array, array.Length + 1);
    array[array.Length - 1] = value;
    return array;
}

Full repo available at https://bitbucket.org/createdbyx/codefarts.utilities-extension-methods-only

/// <summary>
/// Replaces a sequence of array entries at the specified index.
/// </summary>
/// <typeparam name="T">Specifies the generic type of the array.</typeparam>
/// <param name="array">The destination array.</param>
/// <param name="index">The index in the destination array where replacement takes place.</param>
/// <param name="sourceArray">The source array that will replace the existing entries.</param>
/// <returns>Returns the resized and updated destination array.</returns>
/// <exception cref="ArgumentOutOfRangeException">
/// If 'index' is out of bounds of the destination array.
/// </exception>
public static T[] Replace<T>(this T[] array, int index, T[] sourceArray)
{
    if (array == null || sourceArray == null || sourceArray.Length == 0)
    {
        return array;
    }

    if (index < 0)
    {
        throw new ArgumentOutOfRangeException("index");
    }

    if (index > array.Length - 1)
    {
        throw new ArgumentOutOfRangeException("index");
    }

    var expandSize = (index + sourceArray.Length) - array.Length;
    if (expandSize > 0)
    {
        Array.Resize(ref array, array.Length + expandSize);
    }

    sourceArray.CopyTo(array, index);
    return array;
}

Created by: X

Just another personal website in this crazy online world

Name of author Dean Lunz (aka Created by: X)
Computer programming nerd, and tech geek.
About Me -- Resume