Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将等待与动态类型一起使用时行为不一致_C#_.net_Async Await - Fatal编程技术网

C# 将等待与动态类型一起使用时行为不一致

C# 将等待与动态类型一起使用时行为不一致,c#,.net,async-await,C#,.net,Async Await,我试图使用动态来解决由于设计或缺乏设计而带来的不便(如果有兴趣,可以在这里找到“不便”) 简而言之,我需要返回实体实例的集合。类非常简单: [JsonObject] public class Entity { [PrimaryKey] [JsonProperty(PropertyName = "id")] public virtual int Id { get; set; } [JsonIgnore] public string Content { ge

我试图使用
动态
来解决由于设计或缺乏设计而带来的不便(如果有兴趣,可以在这里找到“不便”)

简而言之,我需要返回
实体
实例的集合。类非常简单:

[JsonObject]
public class Entity
{
    [PrimaryKey]
    [JsonProperty(PropertyName = "id")]
    public virtual int Id { get; set; }

    [JsonIgnore]
    public string Content { get; set; }
}
所以
实体
只有
Id
内容
。继承类可能有其他属性,但我只对
内容
部分(复杂JSON)感兴趣

可以通过generic
存储库
访问各种不同的实体。我需要知道具体类的
类型
,因为
T
通过数据提供程序映射到底层SQLite表,该数据提供程序构建在SQLite net ORM之上

例如,如果我有
Schedule:Entity
,那么我将使用
Repository
操作名为
Schedule
的表。这部分很好用

// must be instantiated with concrete class/type inheriting
// from Entity in order to map to correct database table
public class Repository<T> where T : new()
{
    public async virtual Task<IEnumerable<T>> GetAllAsync()
    {
        return await SQLiteDataProvider.Connection.Table<T>().ToListAsync();
    }
    // etc.
}
因此,如果(上面)我使用blocking
.Result
的话,一切都会很有魅力。相反,如果我使用
wait
,代码可能工作,也可能不工作。这似乎真的取决于行星的位置和/或飞行的意大利面怪物的情绪波动

随机地,但更多的时候,给定的线会被抛出

无法强制转换类型为的对象 'System.Runtime.CompilerServices.TaskWaiter'1[System.Collections.Generic.IEnumerable'1[MyNamespace.Schedule]' 键入“System.Runtime.CompilerServices.INotifyCompletion”

我使用的是.NET 4.0扩展框架。

如果
存储库类型是您自己创建的类型,您可以让它基于具有
抽象任务GetAllAsync()
的抽象基类型。然后,因为您的存储库显然已经有了该签名的方法,所以您很好:

public abstract class Repository
{
  public abstract Task<IEnumerable<Entity>> GetAllAsync();
}
公共抽象类存储库
{
公共抽象任务GetAllAsync();
}
然后让您的
存储库
基于存储库

public class Repository<T>: Repository where T: Entity  // Your existing class
{
  public override async Task<IEnumerable<Entity>> GetAllAsync()
  {
    //  Your existing implementation
  }
  //...existing stuff...
}
public-class-Repository:Repository,其中T:Entity//您现有的类
{
公共重写异步任务GetAllAsync()
{
//您现有的实现
}
//…现有的东西。。。
}
然后,当使用它而不是动态时,您可以说:

public async Task<IEnumerable<Entity>> GetAllEntitiesFrom(CollectionArgs args)
{
  var entityType = 
    Type.GetType(
      string.Format(
        "{0}{1}", 
        EntityNamespacePrefix, 
        args.CollectionName), 
      true, 
      true);

  var repositoryType =
    typeof(Repository<>)
    .MakeGenericType(entityType);

  var repository = 
    (Repository) Activator
    .CreateInstance( repositoryType );

  return repository.GetAllAsync();  // await not required
}
公共异步任务GetAllentiesFrom(CollectionArgs)
{
变量entityType=
Type.GetType(
字符串格式(
"{0}{1}", 
EntityNamespacePrefix,
参数集合名称),
是的,
正确的);
var repositoryType=
类型(存储库)
.MakeGenericType(entityType);
var存储库=
(存储库)激活器
.CreateInstance(repositoryType);
return repository.GetAllAsync();//不需要等待
}

完全没有动力

可以通过两个动态调用来实现:

public async Task<IEnumerable<Entity>> GetAllEntitiesFrom(CollectionArgs args)
{
    var entityType = Type.GetType(
        string.Format("{0}{1}", EntityNamespacePrefix, args.CollectionName), true, true);
    var repositoryType = typeof(Repository<>).MakeGenericType(entityType);
    var repository = Activator.CreateInstance(repositoryType);
    var task = (Task)((dynamic)repository).GetAllAsync();
    await task;
    var entities = (IEnumerable<Entity>)((dynamic)task).Result;
    return entities;
}  
公共异步任务GetAllentiesFrom(CollectionArgs)
{
var entityType=Type.GetType(
格式(“{0}{1}”,EntityNamespacePrefix,args.CollectionName),true,true);
var repositoryType=typeof(Repository).MakeGenericType(entityType);
var repository=Activator.CreateInstance(repositoryType);
var task=(任务)((动态)存储库).GetAllAsync();
等待任务;
变量实体=(IEnumerable)((动态)任务).Result;
返回实体;
}  
编辑
尽管上述方法可行,但应该有一个更好的总体设计。不幸的是,MS决定将任务用于异步,因为
Task
是类,所以我们不能从协方差中获益。然而,我们可以通过一个小的通用扩展来实现这一点,只需花费一点GC垃圾。但在IMO中,它大大简化了此类设计/实现。请查看:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

namespace Tests
{
    // General async extensions
    public interface IAwaitable<out TResult>
    {
        IAwaiter<TResult> GetAwaiter();
        TResult Result { get; }
    }
    public interface IAwaiter<out TResult> : ICriticalNotifyCompletion, INotifyCompletion
    {
        bool IsCompleted { get; }
        TResult GetResult();
    }
    public static class AsyncExtensions
    {
        public static IAwaitable<TResult> AsAwaitable<TResult>(this Task<TResult> task) { return new TaskAwaitable<TResult>(task); }
        class TaskAwaitable<TResult> : IAwaitable<TResult>, IAwaiter<TResult>
        {
            TaskAwaiter<TResult> taskAwaiter;
            public TaskAwaitable(Task<TResult> task) { taskAwaiter = task.GetAwaiter(); }
            public IAwaiter<TResult> GetAwaiter() { return this; }
            public bool IsCompleted { get { return taskAwaiter.IsCompleted; } }
            public TResult Result { get { return taskAwaiter.GetResult(); } }
            public TResult GetResult() { return taskAwaiter.GetResult(); }
            public void OnCompleted(Action continuation) { taskAwaiter.OnCompleted(continuation); }
            public void UnsafeOnCompleted(Action continuation) { taskAwaiter.UnsafeOnCompleted(continuation); }
        }
    }
    // Your entity framework
    public abstract class Entity
    {
        // ...
    }
    public interface IRepository<out T>
    {
        IAwaitable<IEnumerable<T>> GetAllAsync();
    }
    public class Repository<T> : IRepository<T> where T : Entity
    {
        public IAwaitable<IEnumerable<T>> GetAllAsync() { return GetAllAsyncCore().AsAwaitable(); }
        protected async virtual Task<IEnumerable<T>> GetAllAsyncCore()
        {
            //return await SQLiteDataProvider.Connection.Table<T>().ToListAsync();

            // Test
            await Task.Delay(1000);
            return await Task.FromResult(Enumerable.Empty<T>());
        }
    }
    public static class Repository
    {
        public static IAwaitable<IEnumerable<Entity>> GetAllEntitiesFrom(string collectionName)
        {
            var entityType = Type.GetType(typeof(Entity).Namespace + "." + collectionName, true, true);
            var repositoryType = typeof(Repository<>).MakeGenericType(entityType);
            var repository = (IRepository<Entity>)Activator.CreateInstance(repositoryType);
            return repository.GetAllAsync();
        }
    }
    // Test
    class EntityA : Entity { }
    class EntityB : Entity { }
    class Program
    {
        static void Main(string[] args)
        {
            var t = Test();
            t.Wait();
        }
        static async Task Test()
        {
            var a = await Repository.GetAllEntitiesFrom(typeof(EntityA).Name);
            var b = await Repository.GetAllEntitiesFrom(typeof(EntityB).Name);
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Runtime.CompilerServices;
使用System.Threading.Tasks;
命名空间测试
{
//通用异步扩展
公共接口IAwaitable
{
IAwaiter();
TResult结果{get;}
}
公共接口:ICriticalNotifyCompletion,INotifyCompletion
{
布尔已完成{get;}
TResult GetResult();
}
公共静态类异步扩展
{
公共静态IAwaitable ASAWITABLE(此任务){返回新任务可等待(任务);}
类任务等待:IAwaitable,IAwaitable
{
任务等待者任务等待者;
public taskAwaiter(Task Task){taskAwaiter=Task.getwaiter();}
public IAwaiter getwaiter(){返回此;}
public bool IsCompleted{get{return taskAwaiter.IsCompleted;}
public TResult Result{get{return taskAwaiter.GetResult();}
public TResult GetResult(){return taskAwaiter.GetResult();}
public void OnCompleted(Action continuation){taskAwaiter.OnCompleted(continuation);}
public void UnsafeOnCompleted(操作继续){taskAwaiter.UnsafeOnCompleted(继续);}
}
}
//您的实体框架
公共抽象类实体
{
// ...
}
公共接口假定
{
IAwaitable GetAllAsync();
}
公共类存储库:IRepository,其中T:Entity
{
公共IAwaitable GetAllAsync(){返回GetAllAsyncCore().AsAwaitable();}
受保护的异步虚拟任务GetAllAsyncCore()
{
//return wait-SQLiteDataProvider.Connection.Table().toListSync();
//试验
等待任务。延迟(1000);
返回wait Task.FromResult(Enumerable.Empty());
}
}
公共静态类存储库
{
公共静态IAwaitable GetAllentiesFrom(字符串集合名称)
{
var entityType=Type.GetType(typeof(Entity.Namespace+“+collectionName,true,true);
var repositoryType=typeof(Repository).MakeGenericType(entityType);
var repository=(IRepository)Activator.CreateInstance(repositoryType);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

namespace Tests
{
    // General async extensions
    public interface IAwaitable<out TResult>
    {
        IAwaiter<TResult> GetAwaiter();
        TResult Result { get; }
    }
    public interface IAwaiter<out TResult> : ICriticalNotifyCompletion, INotifyCompletion
    {
        bool IsCompleted { get; }
        TResult GetResult();
    }
    public static class AsyncExtensions
    {
        public static IAwaitable<TResult> AsAwaitable<TResult>(this Task<TResult> task) { return new TaskAwaitable<TResult>(task); }
        class TaskAwaitable<TResult> : IAwaitable<TResult>, IAwaiter<TResult>
        {
            TaskAwaiter<TResult> taskAwaiter;
            public TaskAwaitable(Task<TResult> task) { taskAwaiter = task.GetAwaiter(); }
            public IAwaiter<TResult> GetAwaiter() { return this; }
            public bool IsCompleted { get { return taskAwaiter.IsCompleted; } }
            public TResult Result { get { return taskAwaiter.GetResult(); } }
            public TResult GetResult() { return taskAwaiter.GetResult(); }
            public void OnCompleted(Action continuation) { taskAwaiter.OnCompleted(continuation); }
            public void UnsafeOnCompleted(Action continuation) { taskAwaiter.UnsafeOnCompleted(continuation); }
        }
    }
    // Your entity framework
    public abstract class Entity
    {
        // ...
    }
    public interface IRepository<out T>
    {
        IAwaitable<IEnumerable<T>> GetAllAsync();
    }
    public class Repository<T> : IRepository<T> where T : Entity
    {
        public IAwaitable<IEnumerable<T>> GetAllAsync() { return GetAllAsyncCore().AsAwaitable(); }
        protected async virtual Task<IEnumerable<T>> GetAllAsyncCore()
        {
            //return await SQLiteDataProvider.Connection.Table<T>().ToListAsync();

            // Test
            await Task.Delay(1000);
            return await Task.FromResult(Enumerable.Empty<T>());
        }
    }
    public static class Repository
    {
        public static IAwaitable<IEnumerable<Entity>> GetAllEntitiesFrom(string collectionName)
        {
            var entityType = Type.GetType(typeof(Entity).Namespace + "." + collectionName, true, true);
            var repositoryType = typeof(Repository<>).MakeGenericType(entityType);
            var repository = (IRepository<Entity>)Activator.CreateInstance(repositoryType);
            return repository.GetAllAsync();
        }
    }
    // Test
    class EntityA : Entity { }
    class EntityB : Entity { }
    class Program
    {
        static void Main(string[] args)
        {
            var t = Test();
            t.Wait();
        }
        static async Task Test()
        {
            var a = await Repository.GetAllEntitiesFrom(typeof(EntityA).Name);
            var b = await Repository.GetAllEntitiesFrom(typeof(EntityB).Name);
        }
    }
}