using System; using System.Linq; using System.Reflection; using Chernobyl.Attribution; using Chernobyl.Collections.Generic.Event; using Chernobyl.Reflection; using Chernobyl.Values; namespace Chernobyl.Dependency { /// /// An that stores the return value of a static /// method. If the return value is attributed with an /// whose key is an /// and whose value is an /// holding an object, then that instance will be uesd to store the return /// value. Otherwise, the return value will be stored in an /// . If the return value is attributed /// with instances then the /// of each is /// used as the key to store and retrieve the value (the return value is /// stored once per key). Note that the static method is not invoked immediately /// to extract the return value; it is invoked when the value is requested. /// [AttributeUsage(AttributeTargets.ReturnValue)] public class SetAttribute : Attribute, IProcessAttribute { /// /// Performs the task requested on the /// passed in. /// /// The /// this was applied to and that is to be /// processed. public void Process(ParameterInfo returnParameter) { IValue value = returnParameter.ToReturnValue(); // Grab the key to store the items. var keyAttributes = returnParameter.GetCustomAttributes(typeof(IKeyAttribute), true) .Cast(); if (keyAttributes.Any()) { // Grab the storage containers to store the instance in. var storages = returnParameter .GetCustomAttributes(typeof(IStorageAttribute>), true) .Cast>>() .DefaultIfEmpty(StaticStorageAttribute.Default); // Store the value in the storages using the key. foreach (IKeyAttribute keyAttribute in keyAttributes) foreach (var storage in storages) storage.Container.Add(keyAttribute.Key, value); } else throw new MethodException( String.Format("Unable to store the result of the return " + "parameter '{0}' on the member '{1}' as the " + "return parameter is not attributed with a " + "'{2}'. ", returnParameter, returnParameter.Member, typeof(IKeyAttribute)), ((MethodBase)returnParameter.Member).ToEnumerable()); } } }