/// <summary>
        /// Loads exported types from a given assembly
        /// </summary>
        /// <param name="assembly">The assembly to search for exported types</param>
        /// <param name="signedOnly">Only load exported types from this assembly if the assembly has been digitally signed</param>
        /// <param name="actionIfUnsigned">If only signed assemblies should be loaded, and this assembly is not signed, load
        /// exported types nonetheless if this action returns true</param>
        public static void LoadExports(Assembly assembly, bool signedOnly = false, Func <Assembly, bool> actionIfUnsigned = null)
        {
            if (signedOnly)
            {
                try
                {
                    X509Certificate.CreateFromSignedFile(assembly.Location);
                }
                catch (CryptographicException e)
                {
                    if (actionIfUnsigned == null || !actionIfUnsigned(assembly))
                    {
                        return;
                    }
                }
            }

            foreach (var type in assembly.GetExportedTypes())
            {
                var custom = type.GetCustomAttributes();
                foreach (var attrib in custom)
                {
                    switch (attrib)
                    {
                    case ExportAttribute ea:
                        ExportedTypes.Add(new ExportedType(type, ea.ExportedType, false));
                        break;

                    case ExportManyAttribute ema:
                        ExportedTypes.Add(new ExportedType(type, ema.ExportedType, true));
                        break;
                    }
                }
            }
        }
 public static void AddExportedType(Type actualType, Type exportedAsType, bool exportMany = false)
 {
     if (ExportedTypes.Any(x => x.ExposedType == exportedAsType))
     {
         throw new Exception($"Type {exportedAsType.FullName} has already been exported");
     }
     ExportedTypes.Add(new ExportedType(actualType, exportedAsType, exportMany));
 }
Пример #3
0
        /// <summary>
        ///     read data from DTO back to POCO.
        ///     NOTE: does not manage array / enumerations as yet
        /// </summary>
        /// <param name="code"></param>
        private void GenerateReadFromDTO(StringBuilder code)
        {
            code.IndentLine(2, $"public static {_poco.Name} ReadFromDTO({_poco.Name} target, {_poco.Name}DTO source)");
            code.IndentLine(2, "{");

            foreach (Tuple <MemberInfo, MemberInfo> item in _members)
            {
                MemberInfo member     = item.Item1;
                Type       memberType = GetDataType(member);
                MemberInfo sibling    = item.Item2;

                if (memberType.IsArray && memberType != typeof(string))
                {
                    Type elementType = memberType.GetElementType();
                    if (elementType != null)
                    {
                        // use TX for exported type to deep copy
                        if (ExportedTypes.Contains(elementType))
                        {
                            code.IndentLine(3, $"target.{member.Name} = source.{ConflateType(sibling)}{member.Name}.Select({elementType}TX.WriteToDTO).ToArray(),");
                        }
                        else
                        {
                            code.IndentLine(3, $"target.{member.Name} = source.{ConflateType(sibling)}{member.Name}.Select().ToArray(),");
                        }
                    }
                }
                else if (!memberType.IsArray && memberType != typeof(string) && typeof(IEnumerable).IsAssignableFrom(memberType))
                {
                    code.IndentLine(3, $"Read{member.Name}FromDTO(target.{ConflateType(sibling)}{member.Name}, source.{member.Name});");
                }
                else if (ExportedTypes.Contains(memberType))
                {
                    code.IndentLine(3, $"{memberType.Name}TX.ReadFromDTO(target.{ConflateType(sibling)}{member.Name}, source.{member.Name});");
                }
                else
                {
                    code.IndentLine(3, $"target.{ConflateType(sibling)}{member.Name} = source.{member.Name};");
                }
            }

            code.IndentLine(3, "return target;");
            code.IndentLine(2, "}");
            code.AppendLine();

            // write methods to copy colections
            foreach (Tuple <MemberInfo, MemberInfo> item in _members)
            {
                MemberInfo member     = item.Item1;
                Type       memberType = GetDataType(member);

                if (!memberType.IsArray && memberType != typeof(string) && typeof(IEnumerable).IsAssignableFrom(memberType))
                {
                    GenerateCopyCollection(code, member);
                }
            }
        }
Пример #4
0
        /// <summary>
        ///     convert existing class reference to equiv DTO for non conflated members
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private string ConvertToDTOType(Type type)
        {
            if (ExportedTypes.Contains(type))
            {
                return(type.Name + "DTO");
            }

            return(CleanTypeName(type));
        }
Пример #5
0
        /// <summary>
        ///     convert c# type to TS
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private string ConvertToTsType(Type type)
        {
            while (true)
            {
                if (type != null && type.IsPrimitive)
                {
                    if (type == typeof(bool))
                    {
                        return("boolean");
                    }

                    return(type == typeof(char) ? "string" : "number");
                }

                if (type == typeof(decimal))
                {
                    return("number");
                }

                if (type == typeof(string))
                {
                    return("string");
                }

                if (type != null && type.IsArray)
                {
                    Type at = type.GetElementType();
                    return(ConvertToTsType(at) + "[]");
                }

                if (typeof(IEnumerable).IsAssignableFrom(type))
                {
                    if (type != null)
                    {
                        Type collectionType = type.GetGenericArguments()[0]; // all my enumerables are typed, so there is a generic argument
                        return(ConvertToTsType(collectionType) + "[]");
                    }
                }

                if (type != null && Nullable.GetUnderlyingType(type) != null)
                {
                    type = Nullable.GetUnderlyingType(type);
                    continue;
                }

                if (type != null && type.IsEnum)
                {
                    return("number");
                }

                if (type != null)
                {
                    return(ExportedTypes.Contains(type) ? type.Name : "any");
                }
            }
        }
Пример #6
0
        public void Execute()
        {
            bool refresh = false;

            for (int i = 0; i < newTypeNodeCreators.Length; i++)
            {
                newTypeNodeCreators[i].Add();
            }
            for (int i = 0; i < existingTypeNodeUpdaters.Length; i++)
            {
                existingTypeNodeUpdaters[i].Add();
            }
            if (origAssemblyDeclSecurities is not null && newAssemblyDeclSecurities is not null)
            {
                modNode.Document.AssemblyDef !.DeclSecurities.Clear();
                foreach (var ds in newAssemblyDeclSecurities)
                {
                    modNode.Document.AssemblyDef.DeclSecurities.Add(ds);
                }
            }
            if (origAssemblyCustomAttributes is not null && newAssemblyCustomAttributes is not null)
            {
                modNode.Document.AssemblyDef !.CustomAttributes.Clear();
                foreach (var ca in newAssemblyCustomAttributes)
                {
                    modNode.Document.AssemblyDef.CustomAttributes.Add(ca);
                }
            }
            if (origModuleCustomAttributes is not null && newModuleCustomAttributes is not null)
            {
                modNode.Document.ModuleDef !.CustomAttributes.Clear();
                foreach (var ca in newModuleCustomAttributes)
                {
                    modNode.Document.ModuleDef.CustomAttributes.Add(ca);
                }
            }
            if (origExportedTypes is not null && newExportedTypes is not null)
            {
                modNode.Document.ModuleDef !.ExportedTypes.Clear();
                foreach (var et in newExportedTypes)
                {
                    modNode.Document.ModuleDef.ExportedTypes.Add(et);
                }
            }
            if (newAssemblyVersion is not null && origAssemblyVersion is not null)
            {
                modNode.Document.AssemblyDef !.Version = newAssemblyVersion;
                refresh = true;
            }
            resourceNodeCreator?.Add();
            if (refresh)
            {
                asmNode?.TreeNode.RefreshUI();
            }
        }
        public static object CreateAndCompose(Type type, params object[] nonComposedParams)
        {
            var nonComposedParamsList = nonComposedParams.ToList();
            var constructor           = type.GetConstructors().FirstOrDefault(x => x.IsPublic);

            if (constructor == null)
            {
                throw new NullReferenceException($"Type {type.FullName} contains no public constructor");
            }
            var constructorArgs = new List <object>();
            var i = 0;

            foreach (var prmInfo in constructor.GetParameters())
            {
                var prm = nonComposedParamsList.FirstOrDefault(x => x.GetType() == prmInfo.ParameterType);
                if (prm == null)
                {
                    foreach (var p in nonComposedParams)
                    {
                        var pt         = p.GetType();
                        var interfaces = pt.GetInterfaces();
                        if (interfaces.Any(x => x == prmInfo.ParameterType))
                        {
                            prm = p;
                            break;
                        }
                    }
                }
                if (prm != null)
                {
                    nonComposedParamsList.Remove(prm);
                    constructorArgs.Add(prm);
                }
                else if (prmInfo.ParameterType.IsInterface)
                {
                    var singletonType = ExportedTypes.FirstOrDefault(x => x.ExposedType == prmInfo.ParameterType)?.ActualType;
                    if (singletonType == null)
                    {
                        throw new NullReferenceException($"No type {prmInfo.ParameterType.FullName} could be matched with any exported type");
                    }
                    var singleton = GetSingleton(singletonType);
                    constructorArgs.Add(singleton);
                }
                else
                {
                    throw new Exception($"Found no matching argument for parameter {prmInfo.Name} in constructor for type {type.FullName}");
                }
            }

            var o = constructor.Invoke(constructorArgs.ToArray());

            Compose(o);

            return(o);
        }
Пример #8
0
        /// <summary>
        /// Tries to find/identify a <see cref="Type"/> by its name
        /// </summary>
        /// <param name="typeName">The name of the <see cref="Type"/></param>
        /// <returns>The <see cref="Type"/> that is defined by the parameter <paramref name="typeName"/></returns>
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="typeName"/> parameter is null
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The <paramref name="typeName"/> parameter is an empty string
        /// </exception>
        public static Type GetTypeFromName(string typeName)
        {
            if (typeName == null)
            {
                throw new ArgumentNullException(nameof(typeName));
            }

            if (typeName.Length == 0)
            {
                throw new ArgumentException("The parameter is an empty string", nameof(typeName));
            }

            var result = ExportedTypes
                         .FirstOrDefault(x =>
                                         x.FullName != null &&
                                         x.FullName.GetHashCode() == typeName.GetHashCode() &&
                                         x.FullName == typeName);

            if (result != null)
            {
                return(result);
            }

            // Maybe the type is just a part of the type name...
            result = ExportedTypes.FirstOrDefault(x => x.FullName != null && x.Name.EndsWith(typeName));

            if (result != null)
            {
                return(result);
            }

            // Else let us loop through all known assemblies and look for the type
            for (int i = 0; i < _assemblies.Count; i++)
            {
                var type = _assemblies[i].GetType(typeName);

                if (type != null)
                {
                    return(type);
                }
            }

            // The last resort
            result = Type.GetType(typeName);

            if (result != null)
            {
                return(result);
            }

            Output.WriteLineError($"The type '{typeName}' defined by the parameter 'typeName' was not found");
            return(null);
        }
Пример #9
0
        /// <summary>
        ///     read through members and build a list, conflating as appropriate
        /// </summary>
        /// <param name="target"></param>
        /// <param name="sibling"></param>
        private void AnalyseFields(Type target, MemberInfo sibling)
        {
            // scan through properties and fields of target type
            // if this is the main class then do not check for existing fields
            foreach (MemberInfo member in GetMembers(target))
            {
                // do we already have this field (or is it part of parent
                // and we are going to deal with it later)?
                if (sibling != null && _existingMembers.Any(mi => mi.Name == member.Name))
                {
                    Log.AppendLine($"  field '{member.Name}' ignored as it already exists;");
                    continue;
                }

                // ReSharper disable once SwitchStatementMissingSomeCases (we are not interested in other member types)
                switch (member.MemberType)
                {
                case MemberTypes.Field:
                    // short cut field
                    FieldInfo fieldInfo = (FieldInfo)member;

                    // see if this is a sibling object
                    if (ExportedTypes.Contains(fieldInfo.FieldType) && IsConflated(member))
                    {
                        AnalyseFields(fieldInfo.FieldType, member);
                        continue;
                    }

                    break;

                case MemberTypes.Property:
                    // short cut field
                    PropertyInfo propertyInfo = (PropertyInfo)member;

                    // see if this is a sibling object
                    if (ExportedTypes.Contains(propertyInfo.PropertyType) && IsConflated(member))
                    {
                        AnalyseFields(propertyInfo.PropertyType, member);
                        continue;
                    }

                    break;

                default:
                    continue;
                }

                _members.Add(new Tuple <MemberInfo, MemberInfo>(member, sibling));
            }
        }
Пример #10
0
        internal static IList <MethodInfo> FindConfigurationMethods(IEnumerable <Assembly> configurationAssemblies, Type configType)
        {
            return(configurationAssemblies
                   .SelectMany(a => a.
#if NET40
                               GetExportedTypes()
#else
                               ExportedTypes
#endif
                               .Select(t => t.GetTypeInfo()).Where(t => t.IsSealed && t.IsAbstract && !t.IsNested))
                   .SelectMany(t => t.DeclaredMethods)
                   .Where(m => m.IsStatic && m.IsPublic && m.IsDefined(typeof(ExtensionAttribute), false))
                   .Where(m => m.GetParameters()[0].ParameterType == configType)
                   .ToList());
        }
        public static object GetExportedTypeInstance(Type type)
        {
            var t = ExportedTypes.FirstOrDefault(x => x.ExposedType == type);

            if (t == null)
            {
                throw new NullReferenceException($"No type {type.FullName} has been exported");
            }
            switch (t.Many)
            {
            case true:
                return(CreateAndCompose(t.ActualType));

            default:
                return(GetSingleton(t.ActualType));
            }
        }
Пример #12
0
        public void CopyTo(Module copy)
        {
            copy._name = _name;
            copy._mvid = _mvid;
            copy._frameworkVersionMoniker = _frameworkVersionMoniker;
            copy._entryPoint = EntryPoint;
            AssemblyReferences.CopyTo(copy.AssemblyReferences);
            ModuleReferences.CopyTo(copy.ModuleReferences);
            Files.CopyTo(copy.Files);
            Types.CopyTo(copy.Types);
            ExportedTypes.CopyTo(copy.ExportedTypes);
            Resources.CopyTo(copy.Resources);
            CustomAttributes.CopyTo(copy.CustomAttributes);

            if (_unmanagedResources != null)
            {
                copy._unmanagedResources = _unmanagedResources.Clone();
            }
        }
        /// <summary>
        /// Compose an object: all properties of the object decorated with an
        /// Import or ImportMany attribute, will be instantiated accordingly.
        /// Alternatively, if a Type if provided, it will be scanned for public
        /// static properties marked for import.
        /// </summary>
        /// <param name="root">The object to compose, or a type if composing must be done for static properties of a class</param>
        public static void Compose(object root)
        {
            if (root == null)
            {
                return;
            }

            PropertyInfo[] infos;
            object         obj;

            if (root is Type rootType)
            {
                obj   = null;
                infos = rootType.GetProperties(
                    BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
            }
            else
            {
                obj   = root;
                infos = root.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            }

            foreach (var prop in infos)
            {
                var browsable = prop.GetCustomAttribute <BrowsableAttribute>();
                if (browsable != null && !browsable.Browsable)
                {
                    continue;
                }

                var attribs = prop.GetCustomAttributes().ToArray();
                if (attribs.Length == 0 && !prop.PropertyType.IsValueType && prop.PropertyType != typeof(string))
                {
                    // Recursive composition is only allowed for generic types for now
                    if (prop.PropertyType.IsGenericType)
                    {
                        Compose(prop.GetValue(root));
                    }
                }

                foreach (var attrib in attribs)
                {
                    ExportedType[] exportedTypes;
                    switch (attrib)
                    {
                    case ImportAttribute ia:
                        exportedTypes = ExportedTypes.Where(x => x.ExposedType == prop.PropertyType).ToArray();
                        if (exportedTypes.Length == 0)
                        {
                            throw new Exception($"No exported type matched imported type {prop.PropertyType.FullName}");
                        }
                        if (exportedTypes.Length > 1)
                        {
                            throw new AmbiguousMatchException($"More than one exported types match imported type {prop.PropertyType.FullName}");
                        }
                        object instance;
                        switch (exportedTypes[0].Many)
                        {
                        case true:
                            instance = CreateAndCompose(exportedTypes[0].ActualType);
                            break;

                        default:
                            instance = GetSingleton(exportedTypes[0].ActualType);
                            break;
                        }
                        prop.SetValue(obj, instance);
                        break;

                    case ImportManyAttribute ima:
                        if (!prop.PropertyType.IsGenericType)
                        {
                            throw new Exception("ImportMany can only be applied on generic types");
                        }

                        exportedTypes = ExportedTypes.Where(x => x.ExposedType == ima.ImportedType).ToArray();
                        var constructedListType = typeof(List <>).MakeGenericType(ima.ImportedType);
                        var instanceList        = (IList)Activator.CreateInstance(constructedListType);
                        foreach (var t in exportedTypes)
                        {
                            var listItem = instance = CreateAndCompose(t.ActualType);
                            instanceList.Add(listItem);
                        }

                        try
                        {
                            prop.SetValue(obj, instanceList);
                        }
                        catch (ArgumentException)
                        {
                            throw new Exception("No setter found for property " + prop.Name + ", or wrong type");
                        }
                        break;
                    }
                }
            }
        }
Пример #14
0
        /// <summary>
        ///     copy data from POCO to new DTO and manage conflation
        /// </summary>
        /// <param name="code"></param>
        private void GenerateWriteToDTO(StringBuilder code)
        {
            code.IndentLine(2, $"public static {_poco.Name}DTO WriteToDTO({_poco.Name} source)");
            code.IndentLine(2, "{");
            code.IndentLine(3, $"return new {_poco.Name}DTO");
            code.IndentLine(4, "{");

            foreach (Tuple <MemberInfo, MemberInfo> item in _members)
            {
                MemberInfo member     = item.Item1;
                Type       memberType = GetDataType(member);
                MemberInfo sibling    = item.Item2;

                if (memberType.IsArray)
                {
                    Type elementType = memberType.GetElementType();
                    if (elementType != null)
                    {
                        // use TX for exported type to deep copy
                        if (ExportedTypes.Contains(elementType))
                        {
                            code.IndentLine(5, $"{member.Name} = source.{ConflateType(sibling)}{member.Name}.Select({elementType}TX.WriteToDTO).ToArray(),");
                        }
                        else
                        {
                            code.IndentLine(5, $"{member.Name} = source.{ConflateType(sibling)}{member.Name}.Select().ToArray(),");
                        }

                        continue;
                    }
                }

                if (memberType != typeof(string) && typeof(IEnumerable).IsAssignableFrom(memberType))
                {
                    // use TX for exported type to deep copy
                    MemberInfo elementType = memberType.GetGenericArguments()[0];
                    if (ExportedTypes.Contains(elementType))
                    {
                        code.IndentLine(5, $"{member.Name} = source.{ConflateType(sibling)}{member.Name}.Select({elementType.Name}TX.WriteToDTO).ToArray(),");
                    }
                    else
                    {
                        code.IndentLine(5, $"{member.Name} = source.{ConflateType(sibling)}{member.Name}.Select().ToArray()");
                    }

                    continue;
                }

                if (ExportedTypes.Contains(memberType))
                {
                    code.IndentLine(5, $"{member.Name} = {ConflateType(sibling)}{member.Name}TX.WriteToDTO(source.{member.Name}),");
                }
                else
                {
                    code.IndentLine(5, $"{member.Name} = source.{ConflateType(sibling)}{member.Name},");
                }
            }

            code.IndentLine(4, "};");
            code.IndentLine(2, "}");
            code.AppendLine("");
        }