Пример #1
0
        public DelegateData(Type type, TypeName className, TypeName interfaceName, TypeBuildStatus buildStatus, WrapperBuilder builder, HashSet <TypeData> typeDatas)
            : base(type, className, interfaceName, buildStatus)
        {
            var invokeMethod = type.GetMethod("Invoke");

            ReturnType = builder.GetTypeData(invokeMethod.ReturnType, typeDatas);
            DependentTypes.UnionWith(ReturnType.GetPublicTypes());
            var parameterInfos = invokeMethod.GetParameters();

            if (parameterInfos?.Length > 0)
            {
                foreach (var parameter in parameterInfos)
                {
                    var parameterType     = parameter.ParameterType;
                    var parameterTypeData = builder.GetTypeData(parameterType, typeDatas);
                    DependentTypes.UnionWith(parameterTypeData.GetPublicTypes());
                    Parameters.Add(new ParameterData(parameterTypeData, parameter.Name, parameter.IsOut));
                }
            }
        }
Пример #2
0
        public override async Task BuildAsync(WrapperBuilder builder, HashSet <TypeData> typeDatas, Func <Type, string, CancellationToken, Task <TextWriter> > writerProvider, CancellationToken cancellationToken = default)
        {
            if (builder.BuildCollectionWrappersAsNecessary)
            {
                BuildStatus = TypeBuildStatus.Building;
                using (var writer = await writerProvider(typeof(Array), "WrapIt.Collections.ListWrapperBase", cancellationToken).ConfigureAwait(false))
                {
                    await writer.WriteAsync(@"using System.Collections.Generic;

namespace WrapIt.Collections
{
    public abstract class ListWrapperBase<T, TWrapped, TInterface> : CollectionWrapper<T, TWrapped, TInterface>, IList<TInterface>, IReadOnlyList<TInterface>
        where TWrapped : TInterface
    {
        internal new IListWrapperBaseInternal InternalWrapper => (IListWrapperBaseInternal)base.InternalWrapper;

        public TWrapped this[int index] { get => InternalWrapper[index]; set => InternalWrapper[index] = value; }

        TInterface IList<TInterface>.this[int index] { get => this[index]; set => this[index] = (TWrapped)value; }

        TInterface IReadOnlyList<TInterface>.this[int index] => this[index];

        internal ListWrapperBase(IListWrapperBaseInternal internalWrapper)
            : base(internalWrapper)
        {
        }

        public int IndexOf(TWrapped item) => InternalWrapper.IndexOf(item);

        int IList<TInterface>.IndexOf(TInterface item) => IndexOf((TWrapped)item);

        void IList<TInterface>.Insert(int index, TInterface item) => InternalWrapper.Insert(index, (TWrapped)item);

        void IList<TInterface>.RemoveAt(int index) => InternalWrapper.RemoveAt(index);

        internal interface IListWrapperBaseInternal : ICollectionWrapperInternal, IList<TWrapped>
        {
        }
    }
}").ConfigureAwait(false);

                    await writer.FlushAsync().ConfigureAwait(false);
                }
            }
            BuildStatus = TypeBuildStatus.Built;

            var collectionWrapperData = builder.GetTypeData(typeof(CollectionWrapperData), typeDatas);

            if (collectionWrapperData.BuildStatus != TypeBuildStatus.Built)
            {
                await collectionWrapperData.BuildAsync(builder, typeDatas, writerProvider, cancellationToken).ConfigureAwait(false);
            }
        }
Пример #3
0
        public ListData(Type type, TypeName className, TypeName interfaceName, TypeData elementType, WrapperBuilder builder, HashSet <TypeData> typeDatas)
            : base(type, className, interfaceName, TypeBuildStatus.NotYetBuilt)
        {
            var listWrapperData = builder.GetTypeData(typeof(ListWrapperData), typeDatas);

            if (listWrapperData.BuildStatus == TypeBuildStatus.NotBuilding)
            {
                listWrapperData.BuildStatus = TypeBuildStatus.NotYetBuilt;
            }
            DependentTypes.UnionWith(listWrapperData.GetPublicTypes());
            ElementType = elementType;
            DependentTypes.UnionWith(elementType.GetPublicTypes());
        }
Пример #4
0
        public DictionaryData(Type type, TypeName className, TypeName interfaceName, TypeData keyType, TypeData valueType, WrapperBuilder builder, HashSet <TypeData> typeDatas)
            : base(type, className, interfaceName, TypeBuildStatus.NotYetBuilt)
        {
            var dictionaryWrapperData = builder.GetTypeData(typeof(DictionaryWrapperData), typeDatas);

            if (dictionaryWrapperData.BuildStatus == TypeBuildStatus.NotBuilding)
            {
                dictionaryWrapperData.BuildStatus = TypeBuildStatus.NotYetBuilt;
            }
            DependentTypes.UnionWith(dictionaryWrapperData.GetPublicTypes());
            KeyType = keyType;
            DependentTypes.UnionWith(keyType.GetPublicTypes());
            ValueType = valueType;
            DependentTypes.UnionWith(valueType.GetPublicTypes());
        }
Пример #5
0
        public override async Task BuildAsync(WrapperBuilder builder, HashSet <TypeData> typeDatas, Func <Type, string, CancellationToken, Task <TextWriter> > writerProvider, CancellationToken cancellationToken = default)
        {
            if (builder.BuildCollectionWrappersAsNecessary)
            {
                BuildStatus = TypeBuildStatus.Building;
                using (var writer = await writerProvider(typeof(Array), "WrapIt.Collections.ListWrapper", cancellationToken).ConfigureAwait(false))
                {
                    await writer.WriteAsync(@"using System;
using System.Collections.Generic;
using System.Linq;

namespace WrapIt.Collections
{
    public sealed class ListWrapper<T, TWrapped, TInterface> : ListWrapperBase<T, TWrapped, TInterface>, IList<TInterface>
        where TWrapped : TInterface
    {
        public static implicit operator ListWrapper<T, TWrapped, TInterface>(List<T> list) => list != null ? new ListWrapper<T, TWrapped, TInterface>(list) : null;

        public static implicit operator List<T>(ListWrapper<T, TWrapped, TInterface> listWrapper) => listWrapper?.ToList();

        public static ListWrapper<T, TWrapped, TInterface> Create(IList<T> list) => list != null ? new ListWrapper<T, TWrapped, TInterface>(list) : null;

        public static ListWrapper<T, TWrapped, TInterface> Create(IList<TInterface> list) => list != null ? new ListWrapper<T, TWrapped, TInterface>(list) : null;

        internal new IListWrapperInternal InternalWrapper => (IListWrapperInternal)base.InternalWrapper;

        public ListWrapper(IList<T> list)
            : base(new StandardListWrapperInternal(list ?? throw new ArgumentNullException(nameof(list))))
        {
        }

        public ListWrapper(IList<TInterface> list)
            : base(new CastedListWrapperInternal(list ?? throw new ArgumentNullException(nameof(list))))
        {
        }

        public List<T> ToList() => InternalWrapper.ToList();

        public void Insert(int index, TWrapped item) => InternalWrapper.Insert(index, item);

        void IList<TInterface>.Insert(int index, TInterface item) => Insert(index, (TWrapped)item);

        public void RemoveAt(int index) => InternalWrapper.RemoveAt(index);

        internal interface IListWrapperInternal : IListWrapperBaseInternal
        {
            List<T> ToList();
        }

        private sealed class StandardListWrapperInternal : StandardCollectionWrapperInternal, IListWrapperInternal
        {
            private readonly IList<T> _list;

            public TWrapped this[int index] { get => Conversion<T, TWrapped>.Wrap(_list[index]); set => _list[index] = Conversion<T, TWrapped>.Unwrap(value); }

            public StandardListWrapperInternal(IList<T> list)
                : base(list)
            {
                _list = list;
            }

            public List<T> ToList() => _list as List<T> ?? _list.ToList();

            public int IndexOf(TWrapped item) => _list.IndexOf(Conversion<T, TWrapped>.Unwrap(item));

            public void Insert(int index, TWrapped item) => _list.Insert(index, Conversion<T, TWrapped>.Unwrap(item));

            public void RemoveAt(int index) => _list.RemoveAt(index);
        }

        private sealed class CastedListWrapperInternal : CastedCollectionWrapperInternal, IListWrapperInternal
        {
            private readonly IList<TInterface> _list;

            public TWrapped this[int index] { get => (TWrapped)_list[index]; set => _list[index] = value; }

            public CastedListWrapperInternal(IList<TInterface> list)
                : base(list)
            {
                _list = list;
            }

            public List<T> ToList() => (List<T>)ToCollection();

            public int IndexOf(TWrapped item) => _list.IndexOf(item);

            public void Insert(int index, TWrapped item) => _list.Insert(index, item);

            public void RemoveAt(int index) => _list.RemoveAt(index);
        }
    }
}").ConfigureAwait(false);

                    await writer.FlushAsync().ConfigureAwait(false);
                }
            }
            BuildStatus = TypeBuildStatus.Built;

            var listWrapperBaseData = builder.GetTypeData(typeof(ListWrapperBaseData), typeDatas);

            if (listWrapperBaseData.BuildStatus != TypeBuildStatus.Built)
            {
                await listWrapperBaseData.BuildAsync(builder, typeDatas, writerProvider, cancellationToken).ConfigureAwait(false);
            }
        }
Пример #6
0
        public override async Task BuildAsync(WrapperBuilder builder, HashSet <TypeData> typeDatas, Func <Type, string, CancellationToken, Task <TextWriter> > writerProvider, CancellationToken cancellationToken = default)
        {
            if (builder.BuildCollectionWrappersAsNecessary)
            {
                BuildStatus = TypeBuildStatus.Building;
                using (var writer = await writerProvider(typeof(Array), "WrapIt.Collections.ArrayWrapper", cancellationToken).ConfigureAwait(false))
                {
                    await writer.WriteAsync(@"using System;
using System.Collections.Generic;

namespace WrapIt.Collections
{
    public sealed class ArrayWrapper<T, TWrapped, TInterface> : ListWrapperBase<T, TWrapped, TInterface>
        where TWrapped : TInterface
    {
        public static implicit operator ArrayWrapper<T, TWrapped, TInterface>(T[] array) => array != null ? new ArrayWrapper<T, TWrapped, TInterface>(array) : null;

        public static implicit operator T[](ArrayWrapper<T, TWrapped, TInterface> arrayWrapper) => arrayWrapper?.ToArray();

        public static ArrayWrapper<T, TWrapped, TInterface> Create(T[] array) => array;

        public static ArrayWrapper<T, TWrapped, TInterface> Create(IList<TInterface> list) => list != null ? new ArrayWrapper<T, TWrapped, TInterface>(list) : null;

        internal new IArrayWrapperInternal InternalWrapper => (IArrayWrapperInternal)base.InternalWrapper;

        public ArrayWrapper(T[] array)
            : base(new StandardArrayWrapperInternal(array ?? throw new ArgumentNullException(nameof(array))))
        {
        }

        public ArrayWrapper(IList<TInterface> list)
            : base(new CastedArrayWrapperInternal(list ?? throw new ArgumentNullException(nameof(list))))
        {
        }

        public T[] ToArray() => InternalWrapper.ToArray();

        internal interface IArrayWrapperInternal : IListWrapperBaseInternal
        {
            T[] ToArray();
        }

        private sealed class StandardArrayWrapperInternal : StandardCollectionWrapperInternal, IArrayWrapperInternal
        {
            private readonly T[] _array;

            public TWrapped this[int index] { get => Conversion<T, TWrapped>.Wrap(_array[index]); set => _array[index] = Conversion<T, TWrapped>.Unwrap(value); }

            public StandardArrayWrapperInternal(T[] array)
                : base(array)
            {
                _array = array;
            }

            public T[] ToArray() => _array;

            public int IndexOf(TWrapped item) => Array.IndexOf(_array, Conversion<T, TWrapped>.Unwrap(item));

            public void Insert(int index, TWrapped item) => throw new NotSupportedException();

            public void RemoveAt(int index) => throw new NotSupportedException();
        }

        private sealed class CastedArrayWrapperInternal : CastedCollectionWrapperInternal, IArrayWrapperInternal
        {
            private readonly IList<TInterface> _list;

            public TWrapped this[int index] { get => (TWrapped)_list[index]; set => _list[index] = value; }

            public override bool IsReadOnly => true;

            public CastedArrayWrapperInternal(IList<TInterface> list)
                : base(list)
            {
                _list = list;
            }

            public override ICollection<T> ToCollection() => ToArray();

            public T[] ToArray()
            {
                var array = new T[Count];
                var i = 0;
                foreach (var item in _list)
                {
                    array[i] = Conversion<T, TWrapped>.Unwrap((TWrapped)item);
                    ++i;
                }
                return array;
            }

            public int IndexOf(TWrapped item) => _list.IndexOf(item);

            public void Insert(int index, TWrapped item) => throw new NotSupportedException();

            public void RemoveAt(int index) => throw new NotSupportedException();

            public override void Add(TWrapped item) => throw new NotSupportedException();

            public override void Clear() => throw new NotSupportedException();

            public override bool Remove(TWrapped item) => throw new NotSupportedException();
        }
    }
}").ConfigureAwait(false);

                    await writer.FlushAsync().ConfigureAwait(false);
                }
            }
            BuildStatus = TypeBuildStatus.Built;

            var listWrapperBaseData = builder.GetTypeData(typeof(ListWrapperBaseData), typeDatas);

            if (listWrapperBaseData.BuildStatus != TypeBuildStatus.Built)
            {
                await listWrapperBaseData.BuildAsync(builder, typeDatas, writerProvider, cancellationToken).ConfigureAwait(false);
            }
        }
Пример #7
0
        public void Initialize(WrapperBuilder builder, HashSet <TypeData> typeDatas, BindingFlags bindingFlags)
        {
            if (_initialized)
            {
                return;
            }

            var isIEnumerable        = false;
            var isGenericIEnumerable = false;

            foreach (var @interface in Type.GetInterfaces())
            {
                if (@interface.IsPublic && !builder.AssembliesWithTypesToWrap.Contains(@interface.Assembly) && builder.InterfaceResolver?.Invoke(Type, @interface) != false)
                {
                    if (!isIEnumerable && @interface == typeof(IEnumerable))
                    {
                        isIEnumerable = true;
                    }
                    if (!isGenericIEnumerable && @interface.IsGenericType && @interface.GetGenericTypeDefinition() == typeof(IEnumerable <>))
                    {
                        isGenericIEnumerable = true;
                    }
                    var interfaceTypeData = (InterfaceData)builder.GetTypeData(@interface, typeDatas);
                    interfaceTypeData.Initialize(builder, typeDatas, bindingFlags);
                    Interfaces.Add(interfaceTypeData);
                }
            }

            var propertyInfos = Type.GetProperties(bindingFlags);

            foreach (var property in propertyInfos)
            {
                if (property.GetAccessors().All(a => IncludeMethod(builder, a, typeDatas, out _)) && builder.PropertyResolver?.Invoke(Type, property) != false)
                {
                    var propertyType     = property.PropertyType;
                    var propertyTypeData = builder.GetTypeData(propertyType, typeDatas);
                    DependentTypes.UnionWith(propertyTypeData.GetPublicTypes());
                    var indexParameters = property.GetIndexParameters();
                    var parameters      = new List <ParameterData>();
                    if (indexParameters?.Length > 0)
                    {
                        foreach (var parameter in indexParameters)
                        {
                            var parameterType     = parameter.ParameterType;
                            var parameterTypeData = builder.GetTypeData(parameterType, typeDatas);
                            DependentTypes.UnionWith(parameterTypeData.GetPublicTypes());
                            parameters.Add(new ParameterData(parameterTypeData, parameter.Name, parameter.IsOut));
                        }
                    }

                    var propertyData = new PropertyData(propertyTypeData, property.Name, property.GetGetMethod() != null, property.GetSetMethod() != null, parameters);
                    foreach (var @interface in Interfaces)
                    {
                        if (@interface.Properties.Any(p => p.Equals(propertyData)))
                        {
                            propertyData.DeclaringInterfaceType = @interface;
                        }
                    }
                    Properties.Add(propertyData);
                }
            }

            Properties = Properties.Distinct().OrderBy(p => p.Name).ToList();

            var methodInfos = Type.GetMethods(bindingFlags);

            foreach (var method in methodInfos)
            {
                if (method.DeclaringType != typeof(object) && !method.IsSpecialName && IncludeMethod(builder, method, typeDatas, out var overrideObject) && builder.MethodResolver?.Invoke(Type, method) != false)
                {
                    var returnType     = method.ReturnType;
                    var returnTypeData = builder.GetTypeData(returnType, typeDatas);
                    DependentTypes.UnionWith(returnTypeData.GetPublicTypes());
                    var parameterInfos = method.GetParameters();
                    var parameters     = new List <ParameterData>();
                    if (parameterInfos?.Length > 0)
                    {
                        foreach (var parameter in parameterInfos)
                        {
                            var parameterType     = parameter.ParameterType;
                            var parameterTypeData = builder.GetTypeData(parameterType, typeDatas);
                            DependentTypes.UnionWith(parameterTypeData.GetPublicTypes());
                            parameters.Add(new ParameterData(parameterTypeData, parameter.Name, parameter.IsOut));
                        }
                    }

                    var methodData = new MethodData(method.Name, returnTypeData, parameters, overrideObject);
                    foreach (var @interface in Interfaces)
                    {
                        if (@interface.Methods.Any(p => p.Equals(methodData)))
                        {
                            methodData.DeclaringInterfaceType = @interface;
                        }
                    }
                    Methods.Add(methodData);
                }
            }

            if (!Type.IsInterface && isIEnumerable && !isGenericIEnumerable)
            {
                var      addMethod  = Methods.SingleOrDefault(m => m.Name == "Add" && m.Parameters.Count == 1);
                TypeData?genericArg = null;
                if (addMethod != null)
                {
                    genericArg = addMethod.Parameters[0].Type;
                }
                var indexers = Properties.Where(p => p.Name == "Item").ToList();
                if (genericArg != null || indexers.Count > 0)
                {
                    genericArg ??= indexers[0].Type;
                    if (indexers.All(i => i.Type.Equals(genericArg)))
                    {
                        var interfaceTypeData = (InterfaceData)builder.GetTypeData(typeof(IEnumerable <>).MakeGenericType(genericArg.Type), typeDatas);
                        interfaceTypeData.Initialize(builder, typeDatas, bindingFlags);
                        Interfaces.Add(interfaceTypeData);
                        for (var i = 0; i < Methods.Count; ++i)
                        {
                            if (Methods[i].Name == "GetEnumerator")
                            {
                                Methods.RemoveAt(i);
                                break;
                            }
                        }
                    }
                }
            }

            Interfaces.Sort((x, y) => string.Compare(x.InterfaceName.Name, y.InterfaceName.Name));

            Methods = Methods.Distinct().OrderBy(m => m.Name).ToList();

            var eventInfos = Type.GetEvents(bindingFlags);

            foreach (var @event in eventInfos)
            {
                if (IncludeMethod(builder, @event.AddMethod, typeDatas, out _) && IncludeMethod(builder, @event.RemoveMethod, typeDatas, out _) && builder.EventResolver?.Invoke(Type, @event) != false)
                {
                    var eventHandlerType     = @event.EventHandlerType;
                    var eventHandlerTypeData = (DelegateData)builder.GetTypeData(eventHandlerType, typeDatas);
                    DependentTypes.UnionWith(eventHandlerTypeData.GetPublicTypes());
                    var invokeMethod   = eventHandlerType.GetMethod("Invoke");
                    var returnType     = invokeMethod.ReturnType;
                    var returnTypeData = builder.GetTypeData(returnType, typeDatas);
                    DependentTypes.UnionWith(returnTypeData.GetPublicTypes());
                    var parameterInfos = invokeMethod.GetParameters();
                    var parameters     = new List <ParameterData>();
                    if (parameterInfos?.Length > 0)
                    {
                        foreach (var parameter in parameterInfos)
                        {
                            var parameterType     = parameter.ParameterType;
                            var parameterTypeData = builder.GetTypeData(parameterType, typeDatas);
                            DependentTypes.UnionWith(parameterTypeData.GetPublicTypes());
                            parameters.Add(new ParameterData(parameterTypeData, parameter.Name, parameter.IsOut));
                        }
                    }

                    var eventData = new EventData(eventHandlerTypeData, @event.Name);
                    foreach (var @interface in Interfaces)
                    {
                        if (@interface.Events.Any(e => e.Equals(eventData)))
                        {
                            eventData.DeclaringInterfaceType = @interface;
                        }
                    }
                    Events.Add(eventData);
                }
            }

            Events = Events.Distinct().OrderBy(e => e.Name).ToList();

            _initialized = true;
        }
Пример #8
0
        public override async Task BuildAsync(WrapperBuilder builder, HashSet <TypeData> typeDatas, Func <Type, string, CancellationToken, Task <TextWriter> > writerProvider, CancellationToken cancellationToken = default)
        {
            if (builder.BuildCollectionWrappersAsNecessary)
            {
                BuildStatus = TypeBuildStatus.Building;
                using (var writer = await writerProvider(typeof(Array), "WrapIt.Collections.DictionaryWrapper", cancellationToken).ConfigureAwait(false))
                {
                    await writer.WriteAsync(@"using System;
using System.Collections;
using System.Collections.Generic;

namespace WrapIt.Collections
{
    public sealed class DictionaryWrapper<TKey, TValue, TValueWrapped, TValueInterface> : IDictionary<TKey, TValueInterface>, IReadOnlyDictionary<TKey, TValueInterface>
        where TValueWrapped : TValueInterface
    {
        public static implicit operator DictionaryWrapper<TKey, TValue, TValueWrapped, TValueInterface>(Dictionary<TKey, TValue> dictionary) => dictionary != null ? new DictionaryWrapper<TKey, TValue, TValueWrapped, TValueInterface>(dictionary) : null;

        public static implicit operator Dictionary<TKey, TValue>(DictionaryWrapper<TKey, TValue, TValueWrapped, TValueInterface> dictionaryWrapper) => dictionaryWrapper?.ToDictionary();

        public static DictionaryWrapper<TKey, TValue, TValueWrapped, TValueInterface> Create(IDictionary<TKey, TValue> dictionary) => dictionary != null ? new DictionaryWrapper<TKey, TValue, TValueWrapped, TValueInterface>(dictionary) : null;

        public static DictionaryWrapper<TKey, TValue, TValueWrapped, TValueInterface> Create(IDictionary<TKey, TValueInterface> dictionary) => dictionary != null ? new DictionaryWrapper<TKey, TValue, TValueWrapped, TValueInterface>(dictionary) : null;

        internal IDictionaryWrapperInternal InternalWrapper { get; }

        public TValueWrapped this[TKey key] { get => InternalWrapper[key]; set => InternalWrapper[key] = value; }

        TValueInterface IDictionary<TKey, TValueInterface>.this[TKey key] { get => this[key]; set => this[key] = (TValueWrapped)value; }

        TValueInterface IReadOnlyDictionary<TKey, TValueInterface>.this[TKey key] => this[key];

        public ICollection<TKey> Keys => InternalWrapper.Keys;

        public CollectionWrapper<TValue, TValueWrapped, TValueInterface> Values => InternalWrapper.Values;

        IEnumerable<TKey> IReadOnlyDictionary<TKey, TValueInterface>.Keys => Keys;

        ICollection<TValueInterface> IDictionary<TKey, TValueInterface>.Values => Values;

        IEnumerable<TValueInterface> IReadOnlyDictionary<TKey, TValueInterface>.Values => Values;

        public int Count => InternalWrapper.Count;

        bool ICollection<KeyValuePair<TKey, TValueInterface>>.IsReadOnly => InternalWrapper.IsReadOnly;

        public DictionaryWrapper(IDictionary<TKey, TValue> dictionary)
        {
            InternalWrapper = new StandardDictionaryWrapper(dictionary ?? throw new ArgumentNullException(nameof(dictionary)));
        }

        public DictionaryWrapper(IDictionary<TKey, TValueInterface> dictionary)
        {
            InternalWrapper = new CastedDictionaryWrapper(dictionary ?? throw new ArgumentNullException(nameof(dictionary)));
        }

        public Dictionary<TKey, TValue> ToDictionary() => InternalWrapper.ToDictionary();

        public IEnumerator<KeyValuePair<TKey, TValueWrapped>> GetEnumerator() => InternalWrapper.GetEnumerator();

        IEnumerator<KeyValuePair<TKey, TValueInterface>> IEnumerable<KeyValuePair<TKey, TValueInterface>>.GetEnumerator()
        {
            foreach (var item in this)
            {
                yield return new KeyValuePair<TKey, TValueInterface>(item.Key, item.Value);
            }
        }

        IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<KeyValuePair<TKey, TValueInterface>>)this).GetEnumerator();

        public void Add(TKey key, TValueWrapped value) => InternalWrapper.Add(key, value);

        void IDictionary<TKey, TValueInterface>.Add(TKey key, TValueInterface value) => Add(key, (TValueWrapped)value);

        void ICollection<KeyValuePair<TKey, TValueInterface>>.Add(KeyValuePair<TKey, TValueInterface> item) => Add(item.Key, (TValueWrapped)item.Value);

        public void Clear() => InternalWrapper.Clear();

        bool ICollection<KeyValuePair<TKey, TValueInterface>>.Contains(KeyValuePair<TKey, TValueInterface> item) => TryGetValue(item.Key, out var value) && EqualityComparer<TValue>.Default.Equals(Conversion<TValue, TValueWrapped>.Unwrap(value), Conversion<TValue, TValueWrapped>.Unwrap((TValueWrapped)item.Value));

        public bool ContainsKey(TKey key) => InternalWrapper.ContainsKey(key);

        void ICollection<KeyValuePair<TKey, TValueInterface>>.CopyTo(KeyValuePair<TKey, TValueInterface>[] array, int arrayIndex)
        {
            if (arrayIndex + Count > array.Length)
            {
                throw new ArgumentOutOfRangeException(""arrayIndex + Count must be less than or equal to array.Length"");
            }

            foreach (var pair in this)
            {
                array[arrayIndex++] = new KeyValuePair<TKey, TValueInterface>(pair.Key, pair.Value);
            }
        }

        public bool Remove(TKey key) => InternalWrapper.Remove(key);

        bool ICollection<KeyValuePair<TKey, TValueInterface>>.Remove(KeyValuePair<TKey, TValueInterface> item) => ((ICollection<KeyValuePair<TKey, TValueInterface>>)this).Contains(item) && Remove(item.Key);

        public bool TryGetValue(TKey key, out TValueWrapped value) => InternalWrapper.TryGetValue(key, out value);

        bool IDictionary<TKey, TValueInterface>.TryGetValue(TKey key, out TValueInterface value)
        {
            var success = TryGetValue(key, out var wrapped);
            value = wrapped;
            return success;
        }

        bool IReadOnlyDictionary<TKey, TValueInterface>.TryGetValue(TKey key, out TValueInterface value) => ((IDictionary<TKey, TValueInterface>)this).TryGetValue(key, out value);

        internal interface IDictionaryWrapperInternal : IDictionary<TKey, TValueWrapped>
        {
            new CollectionWrapper<TValue, TValueWrapped, TValueInterface> Values { get; }

            Dictionary<TKey, TValue> ToDictionary();
        }

        private sealed class StandardDictionaryWrapper : IDictionaryWrapperInternal
        {
            private readonly IDictionary<TKey, TValue> _dictionary;

            public TValueWrapped this[TKey key] { get => Conversion<TValue, TValueWrapped>.Wrap(_dictionary[key]); set => _dictionary[key] = Conversion<TValue, TValueWrapped>.Unwrap(value); }

            public ICollection<TKey> Keys => _dictionary.Keys;

            public CollectionWrapper<TValue, TValueWrapped, TValueInterface> Values => new CollectionWrapper<TValue, TValueWrapped, TValueInterface>(_dictionary.Values);

            ICollection<TValueWrapped> IDictionary<TKey, TValueWrapped>.Values => throw new NotSupportedException();

            public int Count => _dictionary.Count;

            public bool IsReadOnly => _dictionary.IsReadOnly;

            public StandardDictionaryWrapper(IDictionary<TKey, TValue> dictionary)
            {
                _dictionary = dictionary;
            }

            public void Add(TKey key, TValueWrapped value) => _dictionary.Add(key, Conversion<TValue, TValueWrapped>.Unwrap(value));

            public bool ContainsKey(TKey key) => _dictionary.ContainsKey(key);

            public bool Remove(TKey key) => _dictionary.Remove(key);

            public bool TryGetValue(TKey key, out TValueWrapped value)
            {
                var success = _dictionary.TryGetValue(key, out var actual);
                value = Conversion<TValue, TValueWrapped>.Wrap(actual);
                return success;
            }

            public Dictionary<TKey, TValue> ToDictionary() => _dictionary as Dictionary<TKey, TValue> ?? new Dictionary<TKey, TValue>(_dictionary);

            public ICollection<KeyValuePair<TKey, TValue>> ToCollection() => _dictionary;

            public void Add(KeyValuePair<TKey, TValueWrapped> item) => Add(item.Key, item.Value);

            public void Clear() => _dictionary.Clear();

            public bool Contains(KeyValuePair<TKey, TValueWrapped> item) => throw new NotSupportedException();

            public void CopyTo(KeyValuePair<TKey, TValueWrapped>[] array, int arrayIndex) => throw new NotSupportedException();

            public bool Remove(KeyValuePair<TKey, TValueWrapped> item) => throw new NotSupportedException();

            public IEnumerator<KeyValuePair<TKey, TValueWrapped>> GetEnumerator()
            {
                foreach (var pair in _dictionary)
                {
                    yield return new KeyValuePair<TKey, TValueWrapped>(pair.Key, Conversion<TValue, TValueWrapped>.Wrap(pair.Value));
                }
            }

            IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
        }

        private sealed class CastedDictionaryWrapper : IDictionaryWrapperInternal
        {
            private readonly IDictionary<TKey, TValueInterface> _dictionary;

            public TValueWrapped this[TKey key] { get => (TValueWrapped)_dictionary[key]; set => _dictionary[key] = value; }

            public ICollection<TKey> Keys => _dictionary.Keys;

            public CollectionWrapper<TValue, TValueWrapped, TValueInterface> Values => new CollectionWrapper<TValue, TValueWrapped, TValueInterface>(_dictionary.Values);

            ICollection<TValueWrapped> IDictionary<TKey, TValueWrapped>.Values => throw new NotSupportedException();

            public int Count => _dictionary.Count;

            public bool IsReadOnly => _dictionary.IsReadOnly;

            public CastedDictionaryWrapper(IDictionary<TKey, TValueInterface> dictionary)
            {
                _dictionary = dictionary;
            }

            public ICollection<KeyValuePair<TKey, TValue>> ToCollection() => ToDictionary();

            public void Add(TKey key, TValueWrapped value) => _dictionary.Add(key, value);

            public bool ContainsKey(TKey key) => _dictionary.ContainsKey(key);

            public bool Remove(TKey key) => _dictionary.Remove(key);

            public bool TryGetValue(TKey key, out TValueWrapped value)
            {
                var success = _dictionary.TryGetValue(key, out var v);
                value = (TValueWrapped)v;
                return success;
            }

            public Dictionary<TKey, TValue> ToDictionary()
            {
                var dictionary = new Dictionary<TKey, TValue>(_dictionary.Count);
                foreach (var item in _dictionary)
                {
                    dictionary[item.Key] = Conversion<TValue, TValueWrapped>.Unwrap((TValueWrapped)item.Value);
                }
                return dictionary;
            }

            public void Add(KeyValuePair<TKey, TValueWrapped> item) => Add(item.Key, item.Value);

            public void Clear() => _dictionary.Clear();

            public bool Contains(KeyValuePair<TKey, TValueWrapped> item) => throw new NotSupportedException();

            public void CopyTo(KeyValuePair<TKey, TValueWrapped>[] array, int arrayIndex) => throw new NotSupportedException();

            public bool Remove(KeyValuePair<TKey, TValueWrapped> item) => throw new NotSupportedException();

            public IEnumerator<KeyValuePair<TKey, TValueWrapped>> GetEnumerator()
            {
                foreach (var item in _dictionary)
                {
                    yield return new KeyValuePair<TKey, TValueWrapped>(item.Key, (TValueWrapped)item.Value);
                }
            }

            IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
        }
    }
}").ConfigureAwait(false);

                    await writer.FlushAsync().ConfigureAwait(false);
                }
            }
            BuildStatus = TypeBuildStatus.Built;

            var collectionWrapperData = builder.GetTypeData(typeof(CollectionWrapperData), typeDatas);

            if (collectionWrapperData.BuildStatus != TypeBuildStatus.Built)
            {
                await collectionWrapperData.BuildAsync(builder, typeDatas, writerProvider, cancellationToken).ConfigureAwait(false);
            }
        }
Пример #9
0
        public override async Task BuildAsync(WrapperBuilder builder, HashSet <TypeData> typeDatas, Func <Type, string, CancellationToken, Task <TextWriter> > writerProvider, CancellationToken cancellationToken = default)
        {
            if (builder.BuildCollectionWrappersAsNecessary)
            {
                BuildStatus = TypeBuildStatus.Building;
                using (var writer = await writerProvider(typeof(Array), "WrapIt.Collections.CollectionWrapper", cancellationToken).ConfigureAwait(false))
                {
                    await writer.WriteAsync(@"using System;
using System.Collections.Generic;

namespace WrapIt.Collections
{
    public class CollectionWrapper<T, TWrapped, TInterface> : EnumerableWrapper<T, TWrapped, TInterface>, ICollection<TInterface>, IReadOnlyCollection<TInterface>
        where TWrapped : TInterface
    {
        public static CollectionWrapper<T, TWrapped, TInterface> Create(ICollection<T> collection) => collection != null ? new CollectionWrapper<T, TWrapped, TInterface>(collection) : null;

        public static CollectionWrapper<T, TWrapped, TInterface> Create(ICollection<TInterface> collection) => collection != null ? new CollectionWrapper<T, TWrapped, TInterface>(collection) : null;

        internal new ICollectionWrapperInternal InternalWrapper => (ICollectionWrapperInternal)base.InternalWrapper;

        public int Count => InternalWrapper.Count;

        bool ICollection<TInterface>.IsReadOnly => InternalWrapper.IsReadOnly;

        public CollectionWrapper(ICollection<T> collection)
            : base(new StandardCollectionWrapperInternal(collection ?? throw new ArgumentNullException(nameof(collection))))
        {
        }

        public CollectionWrapper(ICollection<TInterface> collection)
            : base(new CastedCollectionWrapperInternal(collection ?? throw new ArgumentNullException(nameof(collection))))
        {
        }

        internal CollectionWrapper(ICollectionWrapperInternal internalWrapper)
            : base(internalWrapper)
        {
        }

        public ICollection<T> ToCollection() => InternalWrapper.ToCollection();

        IEnumerator<TInterface> IEnumerable<TInterface>.GetEnumerator()
        {
            foreach (var item in this)
            {
                yield return item;
            }
        }

        public bool Contains(TWrapped item) => InternalWrapper.Contains(item);

        bool ICollection<TInterface>.Contains(TInterface item) => Contains((TWrapped)item);

        void ICollection<TInterface>.CopyTo(TInterface[] array, int arrayIndex)
        {
            if (arrayIndex + Count > array.Length)
            {
                throw new ArgumentOutOfRangeException(""arrayIndex + Count must be less than or equal to array.Length"");
            }

                foreach (var item in this)
                {
                    array[arrayIndex++] = item;
                }
            }

            void ICollection<TInterface>.Add(TInterface item) => InternalWrapper.Add((TWrapped) item);

            void ICollection<TInterface>.Clear() => InternalWrapper.Clear();

            bool ICollection<TInterface>.Remove(TInterface item) => InternalWrapper.Remove((TWrapped) item);

        internal interface ICollectionWrapperInternal : IEnumerableWrapperInternal, ICollection<TWrapped>
        {
            ICollection<T> ToCollection();
        }

        internal class StandardCollectionWrapperInternal : StandardEnumerableWrapperInternal, ICollectionWrapperInternal
        {
            private readonly ICollection<T> _collection;

            public int Count => _collection.Count;

            public virtual bool IsReadOnly => _collection.IsReadOnly;

            public StandardCollectionWrapperInternal(ICollection<T> collection)
                : base(collection)
            {
                _collection = collection;
            }

            public virtual ICollection<T> ToCollection() => _collection;

            public bool Contains(TWrapped item) => _collection.Contains(Conversion<T, TWrapped>.Unwrap(item));

            public virtual void Add(TWrapped item) => _collection.Add(Conversion<T, TWrapped>.Unwrap(item));

            public virtual void Clear() => _collection.Clear();

            public virtual bool Remove(TWrapped item) => _collection.Remove(Conversion<T, TWrapped>.Unwrap(item));

            void ICollection<TWrapped>.CopyTo(TWrapped[] array, int arrayIndex) => throw new NotSupportedException();
        }

        internal class CastedCollectionWrapperInternal : CastedEnumerableWrapperInternal, ICollectionWrapperInternal
        {
            private readonly ICollection<TInterface> _collection;

            public int Count => _collection.Count;

            public virtual bool IsReadOnly => _collection.IsReadOnly;

            public CastedCollectionWrapperInternal(ICollection<TInterface> collection)
                : base(collection)
            {
                _collection = collection;
            }

            public override IEnumerable<T> ToEnumerable() => ToCollection();

            public virtual ICollection<T> ToCollection()
            {
                var list = new List<T>(Count);
                foreach (var item in _collection)
                {
                    list.Add(Conversion<T, TWrapped>.Unwrap((TWrapped)item));
                }
                return list;
            }

            public bool Contains(TWrapped item) => _collection.Contains(item);

            public virtual void Add(TWrapped item) => _collection.Add(item);

            public virtual void Clear() => _collection.Clear();

            public virtual bool Remove(TWrapped item) => _collection.Remove(item);

            void ICollection<TWrapped>.CopyTo(TWrapped[] array, int arrayIndex) => throw new NotSupportedException();
        }
    }
}").ConfigureAwait(false);

                    await writer.FlushAsync().ConfigureAwait(false);
                }
            }
            BuildStatus = TypeBuildStatus.Built;

            var enumerableWrapperData = builder.GetTypeData(typeof(EnumerableWrapperData), typeDatas);

            if (enumerableWrapperData.BuildStatus != TypeBuildStatus.Built)
            {
                await enumerableWrapperData.BuildAsync(builder, typeDatas, writerProvider, cancellationToken).ConfigureAwait(false);
            }
        }