diff --git a/src/Volo.Abp.AspNetCore.Mvc/Properties/AssemblyInfo.cs b/src/Volo.Abp.AspNetCore.Mvc/Properties/AssemblyInfo.cs index 214a7fbd4f..61be6f3536 100644 --- a/src/Volo.Abp.AspNetCore.Mvc/Properties/AssemblyInfo.cs +++ b/src/Volo.Abp.AspNetCore.Mvc/Properties/AssemblyInfo.cs @@ -1,4 +1,5 @@ using System.Reflection; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following @@ -9,6 +10,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyProduct("Volo.Abp.AspNetCore.Mvc")] [assembly: AssemblyTrademark("")] +[assembly:InternalsVisibleTo("Volo.Abp.AspNetCore.Mvc.Tests")] + // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj b/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj index 828bdfbb27..da9a2c3a86 100644 --- a/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj @@ -13,6 +13,7 @@ + diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ActionDescriptorExtensions.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ActionDescriptorExtensions.cs new file mode 100644 index 0000000000..e12fae5152 --- /dev/null +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ActionDescriptorExtensions.cs @@ -0,0 +1,29 @@ +using System.Reflection; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.Controllers; + +namespace Volo.Abp.AspNetCore.Mvc +{ + public static class ActionDescriptorExtensions + { + public static ControllerActionDescriptor AsControllerActionDescriptor(this ActionDescriptor actionDescriptor) + { + if (!actionDescriptor.IsControllerAction()) + { + throw new AbpException($"{nameof(actionDescriptor)} should be type of {typeof(ControllerActionDescriptor).AssemblyQualifiedName}"); + } + + return actionDescriptor as ControllerActionDescriptor; + } + + public static MethodInfo GetMethodInfo(this ActionDescriptor actionDescriptor) + { + return actionDescriptor.AsControllerActionDescriptor().MethodInfo; + } + + public static bool IsControllerAction(this ActionDescriptor actionDescriptor) + { + return actionDescriptor is ControllerActionDescriptor; + } + } +} diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs new file mode 100644 index 0000000000..cffb5c6f24 --- /dev/null +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs @@ -0,0 +1,149 @@ +using System; +using System.Linq; +using System.Reflection; +using Microsoft.AspNetCore.Mvc.ApiExplorer; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Volo.Abp.Application.Services; +using Volo.Abp.AspNetCore.Mvc.Utils; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Http.Modeling; + +namespace Volo.Abp.AspNetCore.Mvc +{ + public class AspNetCoreApiDescriptionModelProvider : IApiDescriptionModelProvider, ISingletonDependency + { + public ILogger Logger { get; set; } + + private readonly IApiDescriptionGroupCollectionProvider _descriptionProvider; + private readonly AbpAspNetCoreMvcOptions _options; + + public AspNetCoreApiDescriptionModelProvider( + IApiDescriptionGroupCollectionProvider descriptionProvider, + IOptions options) + { + _descriptionProvider = descriptionProvider; + _options = options.Value; + + Logger = NullLogger.Instance; + } + + public ApplicationApiDescriptionModel CreateModel() + { + var model = new ApplicationApiDescriptionModel(); + + foreach (var descriptionGroupItem in _descriptionProvider.ApiDescriptionGroups.Items) + { + foreach (var apiDescription in descriptionGroupItem.Items) + { + if (!apiDescription.ActionDescriptor.IsControllerAction()) + { + continue; + } + + AddApiDescriptionToModel(apiDescription, model); + } + } + + return model; + } + + private void AddApiDescriptionToModel(ApiDescription apiDescription, ApplicationApiDescriptionModel model) + { + var moduleModel = model.GetOrAddModule(GetModuleName(apiDescription)); + var controllerModel = moduleModel.GetOrAddController(GetControllerName(apiDescription)); + + var method = apiDescription.ActionDescriptor.GetMethodInfo(); + + if (controllerModel.Actions.ContainsKey(method.Name)) + { + Logger.LogWarning($"Controller '{controllerModel.Name}' contains more than one action with name '{method.Name}' for module '{moduleModel.Name}'. Ignored: " + apiDescription.ActionDescriptor.GetMethodInfo()); + return; + } + + var returnValue = new ReturnValueApiDescriptionModel(method.ReturnType); + + var actionModel = controllerModel.AddAction(new ActionApiDescriptionModel( + method.Name, + returnValue, + apiDescription.RelativePath, + apiDescription.HttpMethod + )); + + AddParameterDescriptionsToModel(actionModel, method, apiDescription); + } + + private static string GetControllerName(ApiDescription apiDescription) + { + return apiDescription.GroupName?.RemovePostFix(ApplicationService.CommonPostfixes) + ?? apiDescription.ActionDescriptor.AsControllerActionDescriptor().ControllerName; + } + + private void AddParameterDescriptionsToModel(ActionApiDescriptionModel actionModel, MethodInfo method, ApiDescription apiDescription) + { + if (!apiDescription.ParameterDescriptions.Any()) + { + return; + } + + var matchedMethodParamNames = ArrayMatcher.Match( + apiDescription.ParameterDescriptions.Select(p => p.Name).ToArray(), + method.GetParameters().Select(GetMethodParamName).ToArray() + ); + + for (var i = 0; i < apiDescription.ParameterDescriptions.Count; i++) + { + var parameterDescription = apiDescription.ParameterDescriptions[i]; + var matchedMethodParamName = matchedMethodParamNames.Length > i + ? matchedMethodParamNames[i] + : parameterDescription.Name; + + actionModel.AddParameter(new ParameterApiDescriptionModel( + parameterDescription.Name, + matchedMethodParamName, + parameterDescription.Type, + parameterDescription.RouteInfo?.IsOptional ?? false, + parameterDescription.RouteInfo?.DefaultValue, + parameterDescription.RouteInfo?.Constraints?.Select(c => c.GetType().Name).ToArray(), + parameterDescription.Source.Id + ) + ); + } + } + + public string GetMethodParamName(ParameterInfo parameterInfo) + { + var modelNameProvider = parameterInfo.GetCustomAttributes() + .OfType() + .FirstOrDefault(); + + if (modelNameProvider == null) + { + return parameterInfo.Name; + } + + return modelNameProvider.Name; + } + + private string GetModuleName(ApiDescription apiDescription) + { + var controllerType = apiDescription.ActionDescriptor.AsControllerActionDescriptor().ControllerTypeInfo.AsType(); + if (controllerType == null) + { + return AbpControllerAssemblySetting.DefaultServiceModuleName; + } + + foreach (var controllerSetting in _options.AppServiceControllers.ControllerAssemblySettings) + { + if (Equals(controllerType.Assembly, controllerSetting.Assembly)) + { + return controllerSetting.ModuleName; + } + } + + return AbpControllerAssemblySetting.DefaultServiceModuleName; + } + } +} diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ControllerAssemblySettingList.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ControllerAssemblySettingList.cs index 36112a9ccc..c7701994bc 100644 --- a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ControllerAssemblySettingList.cs +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ControllerAssemblySettingList.cs @@ -10,7 +10,7 @@ namespace Volo.Abp.AspNetCore.Mvc [CanBeNull] public AbpControllerAssemblySetting GetSettingOrNull(Type controllerType) { - return this.FirstOrDefault(controllerSetting => controllerSetting.Assembly == controllerType.GetAssembly()); + return this.FirstOrDefault(controllerSetting => controllerSetting.Assembly == controllerType.Assembly); } } } \ No newline at end of file diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Utils/ArrayMatcher.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Utils/ArrayMatcher.cs new file mode 100644 index 0000000000..f1b5b2b8e6 --- /dev/null +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Utils/ArrayMatcher.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; + +namespace Volo.Abp.AspNetCore.Mvc.Utils +{ + internal static class ArrayMatcher + { + public static T[] Match(T[] sourceArray, T[] destinationArray) + { + var result = new List(); + + var currentMethodParamIndex = 0; + var parentItem = default(T); + + foreach (var sourceItem in sourceArray) + { + if (currentMethodParamIndex < destinationArray.Length) + { + var destinationItem = destinationArray[currentMethodParamIndex]; + + if (EqualityComparer.Default.Equals(sourceItem, destinationItem)) + { + parentItem = default(T); + currentMethodParamIndex++; + } + else + { + if (parentItem == null) + { + parentItem = destinationItem; + currentMethodParamIndex++; + } + } + } + + var resultItem = EqualityComparer.Default.Equals(parentItem, default(T)) ? sourceItem : parentItem; + result.Add(resultItem); + } + + return result.ToArray(); + } + } +} diff --git a/src/Volo.Abp.Http/Volo.Abp.Http.csproj b/src/Volo.Abp.Http/Volo.Abp.Http.csproj index 181e749dfc..d4031e3399 100644 --- a/src/Volo.Abp.Http/Volo.Abp.Http.csproj +++ b/src/Volo.Abp.Http/Volo.Abp.Http.csproj @@ -16,8 +16,4 @@ - - - - \ No newline at end of file diff --git a/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ActionApiDescriptionModel.cs b/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ActionApiDescriptionModel.cs new file mode 100644 index 0000000000..b897d8a900 --- /dev/null +++ b/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ActionApiDescriptionModel.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; + +namespace Volo.Abp.Http.Modeling +{ + [Serializable] + public class ActionApiDescriptionModel + { + public string Name { get; } + + public string HttpMethod { get; } + + public string Url { get; } + + public IList Parameters { get; } + + public ReturnValueApiDescriptionModel ReturnValue { get; } + + private ActionApiDescriptionModel() + { + + } + + public ActionApiDescriptionModel(string name, ReturnValueApiDescriptionModel returnValue, string url, string httpMethod = null) + { + Name = name; + ReturnValue = returnValue; + Url = url; + HttpMethod = httpMethod; + + Parameters = new List(); + } + + public ParameterApiDescriptionModel AddParameter(ParameterApiDescriptionModel parameter) + { + Parameters.Add(parameter); + return parameter; + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApplicationApiDescriptionModel.cs b/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApplicationApiDescriptionModel.cs new file mode 100644 index 0000000000..6438c5e9b8 --- /dev/null +++ b/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApplicationApiDescriptionModel.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Volo.Abp.Http.Modeling +{ + [Serializable] + public class ApplicationApiDescriptionModel + { + public IDictionary Modules { get; } + + public ApplicationApiDescriptionModel() + { + Modules = new Dictionary(); + } + + public ModuleApiDescriptionModel AddModule(ModuleApiDescriptionModel module) + { + if (Modules.ContainsKey(module.Name)) + { + throw new AbpException("There is already a module with same name: " + module.Name); + } + + return Modules[module.Name] = module; + } + + public ModuleApiDescriptionModel GetOrAddModule(string name) + { + return Modules.GetOrAdd(name, () => new ModuleApiDescriptionModel(name)); + } + + public ApplicationApiDescriptionModel CreateSubModel(string[] modules = null, string[] controllers = null, string[] actions = null) + { + var subModel = new ApplicationApiDescriptionModel(); + + foreach (var module in Modules.Values) + { + if (modules == null || modules.Contains(module.Name)) + { + subModel.AddModule(module.CreateSubModel(controllers, actions)); + } + } + + return subModel; + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ControllerApiDescriptionModel.cs b/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ControllerApiDescriptionModel.cs new file mode 100644 index 0000000000..ee30fb82ce --- /dev/null +++ b/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ControllerApiDescriptionModel.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Volo.Abp.Http.Modeling +{ + [Serializable] + public class ControllerApiDescriptionModel + { + public string Name { get; } + + public IDictionary Actions { get; } + + private ControllerApiDescriptionModel() + { + + } + + public ControllerApiDescriptionModel(string name) + { + Name = name; + + Actions = new Dictionary(); + } + + public ActionApiDescriptionModel AddAction(ActionApiDescriptionModel action) + { + if (Actions.ContainsKey(action.Name)) + { + throw new AbpException( + $"Can not add more than one action with same name to the same controller. Controller: {Name}, Action: {action.Name}." + ); + } + + return Actions[action.Name] = action; + } + + public ControllerApiDescriptionModel CreateSubModel(string[] actions) + { + var subModel = new ControllerApiDescriptionModel(Name); + + foreach (var action in Actions.Values) + { + if (actions == null || actions.Contains(action.Name)) + { + subModel.AddAction(action); + } + } + + return subModel; + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/IApiDescriptionModelProvider.cs b/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/IApiDescriptionModelProvider.cs new file mode 100644 index 0000000000..35334fae33 --- /dev/null +++ b/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/IApiDescriptionModelProvider.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.Http.Modeling +{ + public interface IApiDescriptionModelProvider + { + ApplicationApiDescriptionModel CreateModel(); + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ModuleApiDescriptionModel.cs b/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ModuleApiDescriptionModel.cs new file mode 100644 index 0000000000..f87db87693 --- /dev/null +++ b/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ModuleApiDescriptionModel.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Volo.Abp.Http.Modeling +{ + [Serializable] + public class ModuleApiDescriptionModel + { + public string Name { get; set; } + + public IDictionary Controllers { get; } + + private ModuleApiDescriptionModel() + { + + } + + public ModuleApiDescriptionModel(string name) + { + Name = name; + + Controllers = new Dictionary(); + } + + public ControllerApiDescriptionModel AddController(ControllerApiDescriptionModel controller) + { + if (Controllers.ContainsKey(controller.Name)) + { + throw new AbpException($"There is already a controller with name: {controller.Name} in module: {Name}"); + } + + return Controllers[controller.Name] = controller; + } + + public ControllerApiDescriptionModel GetOrAddController(string name) + { + return Controllers.GetOrAdd(name, () => new ControllerApiDescriptionModel(name)); + } + + public ModuleApiDescriptionModel CreateSubModel(string[] controllers, string[] actions) + { + var subModel = new ModuleApiDescriptionModel(Name); + + foreach (var controller in Controllers.Values) + { + if (controllers == null || controllers.Contains(controller.Name)) + { + subModel.AddController(controller.CreateSubModel(actions)); + } + } + + return subModel; + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ParameterApiDescriptionModel.cs b/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ParameterApiDescriptionModel.cs new file mode 100644 index 0000000000..a5d0dde0a1 --- /dev/null +++ b/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ParameterApiDescriptionModel.cs @@ -0,0 +1,41 @@ +using System; + +namespace Volo.Abp.Http.Modeling +{ + [Serializable] + public class ParameterApiDescriptionModel + { + public string NameOnMethod { get; } + + public string Name { get; } + + public Type Type { get; } + + public string TypeAsString { get; } + + public bool IsOptional { get; } + + public object DefaultValue { get; } + + public string[] ConstraintTypes { get; } + + public string BindingSourceId { get; } + + private ParameterApiDescriptionModel() + { + + } + + public ParameterApiDescriptionModel(string name, string nameOnMethod, Type type, bool isOptional = false, object defaultValue = null, string[] constraintTypes = null, string bindingSourceId = null) + { + Name = name; + NameOnMethod = nameOnMethod; + Type = type; + TypeAsString = type.FullName; + IsOptional = isOptional; + DefaultValue = defaultValue; + ConstraintTypes = constraintTypes; + BindingSourceId = bindingSourceId; + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ReturnValueApiDescriptionModel.cs b/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ReturnValueApiDescriptionModel.cs new file mode 100644 index 0000000000..83b4cba346 --- /dev/null +++ b/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ReturnValueApiDescriptionModel.cs @@ -0,0 +1,17 @@ +using System; + +namespace Volo.Abp.Http.Modeling +{ + [Serializable] + public class ReturnValueApiDescriptionModel + { + public Type Type { get; } + public string TypeAsString { get; } + + public ReturnValueApiDescriptionModel(Type type) + { + Type = type; + TypeAsString = type.FullName; + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp/System/AbpTypeExtensions.cs b/src/Volo.Abp/System/AbpTypeExtensions.cs deleted file mode 100644 index 2cbd8dea77..0000000000 --- a/src/Volo.Abp/System/AbpTypeExtensions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Reflection; - -namespace System -{ - public static class AbpTypeExtensions - { - //TODO: This method can be removed because not needed anymore! - public static Assembly GetAssembly(this Type type) - { - return type.GetTypeInfo().Assembly; - } - } -} diff --git a/src/Volo.Abp/Volo/Abp/Modularity/AbpModuleDescriptor.cs b/src/Volo.Abp/Volo/Abp/Modularity/AbpModuleDescriptor.cs index 69fada953c..7413e1154f 100644 --- a/src/Volo.Abp/Volo/Abp/Modularity/AbpModuleDescriptor.cs +++ b/src/Volo.Abp/Volo/Abp/Modularity/AbpModuleDescriptor.cs @@ -33,7 +33,7 @@ namespace Volo.Abp.Modularity } Type = type; - Assembly = type.GetAssembly(); + Assembly = type.Assembly; Instance = instance; IsLoadedAsPlugIn = isLoadedAsPlugIn; diff --git a/src/Volo.Abp/Volo/Abp/Reflection/AssemblyFinder.cs b/src/Volo.Abp/Volo/Abp/Reflection/AssemblyFinder.cs index 6d90a8fb5c..8178f1046b 100644 --- a/src/Volo.Abp/Volo/Abp/Reflection/AssemblyFinder.cs +++ b/src/Volo.Abp/Volo/Abp/Reflection/AssemblyFinder.cs @@ -30,7 +30,7 @@ namespace Volo.Abp.Reflection foreach (var module in _moduleContainer.Modules) { - assemblies.Add(module.Type.GetAssembly()); + assemblies.Add(module.Type.Assembly); } return assemblies.Distinct().ToImmutableList(); diff --git a/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Utils/ArrayMacther_Tests.cs b/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Utils/ArrayMacther_Tests.cs new file mode 100644 index 0000000000..a066622748 --- /dev/null +++ b/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Utils/ArrayMacther_Tests.cs @@ -0,0 +1,19 @@ +using Xunit; + +namespace Volo.Abp.AspNetCore.Mvc.Utils +{ + public class ArrayMacther_Tests + { + [Theory] + [InlineData( + new[] { "p1", "p2.a1", "p2.a2.b1", "p2.a2.b2", "p3", "p4", "p5.c1", "p5.c2" }, + new[] { "p1", "p2", "p3", "p4", "p5" }, + new[] { "p1", "p2", "p2", "p2", "p3", "p4", "p5", "p5" }) + ] + public void Should_Find_Correct_Items(string[] sourceArray, string[] destinationArray, string[] expectedArray) + { + var result = ArrayMatcher.Match(sourceArray, destinationArray); + Assert.Equal(expectedArray, result); + } + } +} diff --git a/test/Volo.Abp.Tests/Volo/Abp/Reflection/AssemblyFinder_Tests.cs b/test/Volo.Abp.Tests/Volo/Abp/Reflection/AssemblyFinder_Tests.cs index 92cd5aaf64..37c5b01518 100644 --- a/test/Volo.Abp.Tests/Volo/Abp/Reflection/AssemblyFinder_Tests.cs +++ b/test/Volo.Abp.Tests/Volo/Abp/Reflection/AssemblyFinder_Tests.cs @@ -30,7 +30,7 @@ namespace Volo.Abp.Reflection foreach (var moduleType in moduleTypes) { - assemblyFinder.Assemblies.ShouldContain(moduleType.GetAssembly()); + assemblyFinder.Assemblies.ShouldContain(moduleType.Assembly); } } diff --git a/test/Volo.Abp.Tests/Volo/Abp/Reflection/TypeFinder_Tests.cs b/test/Volo.Abp.Tests/Volo/Abp/Reflection/TypeFinder_Tests.cs index 4bbaf34400..c9876875ed 100644 --- a/test/Volo.Abp.Tests/Volo/Abp/Reflection/TypeFinder_Tests.cs +++ b/test/Volo.Abp.Tests/Volo/Abp/Reflection/TypeFinder_Tests.cs @@ -18,8 +18,8 @@ namespace Volo.Abp.Reflection var fakeAssemblyFinder = Substitute.For(); fakeAssemblyFinder.Assemblies.Returns(new List { - typeof(AbpKernelModule).GetAssembly(), - typeof(TypeFinder_Tests).GetAssembly() + typeof(AbpKernelModule).Assembly, + typeof(TypeFinder_Tests).Assembly }); //Act