Linqpad: LINQPad.Util.Cache throws error if query file is modified, saved and re-run. "Cannot load type" error - linqpad

Using the amazing LinqPad with a C# script. Get an error using the Util.Cache storing a custom class declared in the same script. How to resolve, other than restarting LinqPad please?
Reproduce error:
Add any char to the comment
save file
run again
Error raised:
Cannot load type 'UserQuery+IPerson' from cache.
Data
(0 items)
HelpLink null
HResult -2146233088
InnerException null
Message Cannot load type 'UserQuery+IPerson' from cache.
Source LINQPad.Runtime
StackTrace at LINQPad.Util.Cache[T](Func`1 dataFetcher, String key, Boolean& fromCache)
at LINQPad.Util.Cache[T](Func`1 dataFetcher, String key)
at UserQuery.Main(), line 3
TargetSite
RuntimeMethodInfo•••
CacheConverter.CanConvert (Type sourceType, Type targetType, HashSet<TypeType> visitedTypes)
Linqpad query code
Here is the code being run:
void Main()
{
IPerson p = Util.Cache<IPerson>(()=>new Person("Bob"), "person_bob9");
p.Dump();
// add any char after here, save re-run, error thrown: a
}
interface IPerson{string Name {get;init;}}
class Person:IPerson
{
public Person(string name)=> Name = name;
public string Name { get; init; }
}
Notes
Maybe this happens because the Person class is compiled by linqpad into a dll each time the file is modified and run. When an instance of Person is stored in a cache, this might differ from the current Person type declaration, hence the error.

i guess it works with functions
void Main()
{
var p = Util.Cache<Person>(() => AddPerson("uuuu"), "cached_user").Dump();
p.Dump();
string s = "";
}
interface IPerson
{
string Name { get; init; }
}
[Serializable]
public class Person : IPerson
{
public Person(string name) => Name = name;
public string Name { get; init; }
}
public Person AddPerson(string Name)
{
//Thread.Sleep(1000);
return new Person(Name);
}

Related

Use of "RecordCondition.ExcludeIfMatchRegex"

Library version: v2.0.0.0
I would like to use ExcludeIfMatchRegex to exclude certain lines in the input file.
I have tested next code but the system is displaying the usual message error Object reference not set to an instance of an object.
If I remove the line containing "ConditionalRecord", the system reads the file and returns the usual validation messages.
using FileHelpers;
using System;
[IgnoreEmptyLines()]
[ConitionalRecord(RecordCondition.ExcludeIfMatchRegex, "[0-9 A-Za-z.,]{1}S[0-9 A-Za-z.,]{10}")]
[FixedLengthRecord(FixedMode.ExactLength)]
public sealed class PurchaseOrder : INotifyRead
{
[FieldFixedLength(1)]
[FieldTrim(TrimMode.Both)]
public string C;
[FieldFixedLength(1)]
[FieldTrim(TrimMode.Both)]
public string A;
[FieldFixedLength(10)]
[FieldTrim(TrimMode.Both)]
public string item;
public void AfterRead(EngineBase engine, string line)
{
// not exist the property "SkipThisRecord"??
}
}
Looks like a small bug in the 2.0.0.0 library.
When the FileHelpers engine reads a file but ALL lines are excluded AND the class is decorated with INotifyRead it throws the Object Reference error.
However you can work around it by using the AfterReadRecord event instead.
[IgnoreEmptyLines()]
[ConditionalRecord(RecordCondition.ExcludeIfMatchRegex, "[0-9 A-Za-z.,]{1}S[0-9 A-Za-z.,]{10}")]
[FixedLengthRecord(FixedMode.ExactLength)]
public sealed class PurchaseOrder
{
[FieldFixedLength(1)]
[FieldTrim(TrimMode.Both)]
public string C;
[FieldFixedLength(1)]
[FieldTrim(TrimMode.Both)]
public string A;
[FieldFixedLength(10)]
[FieldTrim(TrimMode.Both)]
public string item;
}
internal class Program
{
static void Main(string[] args)
{
FileHelperEngine engine = new FileHelperEngine(typeof(PurchaseOrder));
// use the AfterReadRecord event instead of the INotifyRead interface
engine.AfterReadRecord += Engine_AfterReadRecord;
// The record will be skipped because of the Regex
var records = engine.ReadString("0S0123456789");
Debug.Assert(records.Length == 0);
Console.Write("All OK. No records were imported.");
Console.ReadKey();
}
// Define the event here instead of in your FileHelpers class
private static void Engine_AfterReadRecord(EngineBase engine, AfterReadRecordEventArgs e)
{
// not exist the property "SkipThisRecord"??
}

Implementing ICloneable with protobuf-net

Can you please explain why the following piece of code fails to work?
static void Main(string[] args)
{
var simpleObject = new SimpleObjectDTO { Id = 1, Name = "Jacob" };
const string format = "{2} object properties are: Id {0} Name {1}";
Console.WriteLine(format, simpleObject.Id, simpleObject.Name, "Original");
var clone = simpleObject.Clone() as SimpleObjectDTO;
// ReSharper disable PossibleNullReferenceException
Console.WriteLine(format, clone.Id, clone.Name, "Clone");
// ReSharper restore PossibleNullReferenceException
Console.ReadLine();
}
where
[ProtoContract]
public class SimpleObjectDTO : ICloneable
{
[ProtoMember(1)]
public int Id { get; set; }
[ProtoMember(2)]
public string Name { get; set; }
public object Clone()
{
using (var stream = new MemoryStream())
{
Serializer.Serialize(stream, this);
stream.Flush();
var clone = Serializer.Deserialize<SimpleObjectDTO>(stream);
return clone;
}
}
}
The code runs just fine but the deserialized object has 0 and an empty string
as the appropriate properties' values.
Upd.:
If I serialize into a binary file and then open if for reading thus creating a new stream
the code works. Is there any possibility of avoiding intermediate binary files and using only one stream for both serializing and deserializing?
Thr problem is the stream's position needs to be reset to zero.
As an alternative:
return Serializer.DeepClone(this);
Figured out the issue, forgot to reset the memory stream's position

mono rises unexpected compiler errors

I have the following class
public class LockRequest
{
public int Id { get; set; }
public string TypeName { get; set; }
public bool Ok { get; set; }
public LockRequest ( int id, string t)
{
Id = id;
TypeName = t;
}
}
Then, it's referenced in a delegate, as follows
private static void ReceiveLockRequest<LockRequest>(PacketHeader header, Connection connection, LockRequest input )
{
LockRequest lr = new LockRequest(1, "SomeTypeName" );
Console.WriteLine( String.Format ( "{0} ", input.TypeName) );
}
When compiling, both lines from the delegate rises compiler errors.
The line with the "new()", produces "Cannot create an instance of the type class 'LockRequest' because it does not have the 'new()' constraint.
The line which would show some of the input data gives "The type 'Lockrequest' does not contains a definition for 'TypeName' and no extension method 'TypeName' ... etc".
Could someone explain why is this behaviour?
My dev environment is Ubuntu 10.04 (64 bits) and Monodevelop 2.8.6.3
TIA
Could add some info.
I changed the name of the class, and the thing compiled. The whole class is to be serialised by ProtoBuf, so it must be decorated with attributes. Here are is a sample
[ProtoContract]
public class Foo
{
[ProtoMember(1)]
public int { get; protected set; }
[ProtoMember(2)]
public string TypeName { get; protected set; }
...
Just after I added the attributes, mono stop compiling. Same erors raise again.
To test it, I commented the attributes, do a Clean All, an recompile. The errors raise again, as if MonoDevelop cached them.
I need some help more than after the initial post.
2013-10-31
Thank you, Jester. It´s an event handler, from NetworkCommDotNet library.
My faults:
1) The first error (members not recognized) raises from the fact that (somewhat astobishing) the "input" argument comes as a plain object. Casting it in another method does the trick.
2) The error regarding the instanciation: the delegate definition in the library have a where clause wich states that T must be class, but no the new() constraint.
That's not a delegate, that's a generic method.
It's not clear what you want to do and why do you need a generic method.
If you really do, then try something along the lines of:
private static void ReceiveLockRequest<T>(PacketHeader header, Connection connection, T input) where T:LockRequest
PS: your development environment is very old, consider upgrading.

toList() System.InvalidCastException was unhandled by user code

I have written a WCF service using LINQ to SQL (using the following article at codeporject). I am facing the invalid cast exception when i invoke the .ToList() method of an object after i have already made a wcf function call of the same service against the same database.
The exception is:
System.InvalidCastException was unhandled by user code
Message=Specified cast is not valid.
Source=System.Data
StackTrace:
at System.Data.SqlClient.SqlBuffer.get_Int64()
at System.Data.SqlClient.SqlDataReader.GetInt64(Int32 i)
at Read_Command(ObjectMaterializer`1 )
at System.Data.Linq.SqlClient.ObjectReaderCompiler.ObjectReader`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at SystemsManager.ACS.GetCommands(Int64 agentId) in E:\Projects\SystemsManager\AgentControlService\ACS.svc.cs:line 167
at SyncInvokeGetCommands(Object , Object[] , Object[] )
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
InnerException:
The specific line i am having issue is with the ToList() method
public List<Command> GetCommands(long agentId)
{
var cmd = from command in db.Command where (command.AgentId == agentId) select command;
return cmd.ToList();
}
When debugging, the return statment throws exception. When view the value of cmd.ToList() in Quick Watch of VS 2010, the exception is shown.
Now the strangest thing is: Pressing "Re-Evaluate" button a couple of times changes the exception to required object list in Quick watch. Infact i have to press "Re-evaluate" at least three times.
I have generated client using svcutil tool after my most recent changes to the service/database.
I am calling the method using the following code from a windows service:
var agent = client.GetAgentByIpAddress(myIPAddress);
client.Close();
if (agent != null)
{
if (agent.AgentId != -1)
{
client = new ACSClient();
var command = client.GetCommands(agent.AgentId);
.....
Here is the model of Command in the interface of the wcf service.
[DataContract]
[Table(Name = "Command")]
public class Command
{
[DataMember, Column(IsPrimaryKey = true, Name = "Command_Id", AutoSync = AutoSync.OnInsert, IsDbGenerated = true, DbType = "Bigint NOT null identity")]
public long CommandId { get; set; }
[DataMember, Column(Name = "Agent_Id")]
public long AgentId { get; set; }
[DataMember, Column(Name = "Name")]
public string CommandName { get; set; }
[DataMember, Column(Name = "Paramters")]
public string CommandParamters { get; set; }
[DataMember, Column(Name = "Is_Fetched")]
public bool IsFectched { get; set; }
[DataMember, Column(Name = "Status")]
public long Status { get; set; }
[DataMember, Column(Name = "Response")]
public string Response { get; set; }
[DataMember, Column(Name = "Created")]
public DateTime Created { get; set; }
[DataMember, Column(Name = "Last_Modified")]
public DateTime LastModified { get; set; }
[DataMember, Column(Name = "Is_Enabled")]
public bool IsEnabled { get; set; }
}
Important thing is: My database file is located in AppData folder of the WCF service. I am using only one instance of db object (refer to 1st code block above) throughout my wcf service and i am wondering if this could be cause of the problem???
Also, i have called a couple of similar method of this very same wcf service from a desktop application but i have not faced any such issue.
Please help. if more details are needed, please state so.. The only thing that can come to mind is that perhaps the database is in use and when another connection is made to the database by the service, it fails. and retrying it a couple of times using the Quick Watch > Re-evaluate button displays the required values in the watch window without throwing any error.
Kindly help on this one. Quick responses are highly appreciated.
Thanks.
Steve
Never mind guys. I solved it.
For anyone else who is getting invalid cast exception, here is the solution.
The error only occurs when actual class model is different that the database.
If you have created the class model by hand coding it, the you must match each column name of the table to your corresponding class. LINQ to sql encounters error when it cannot convert a database type to .Net type and throws invalid cast exception.
So in most cases, either fixing the error manually in the model class or regenerating the class will solve the problem.

WCF and ServiceKnownType with many assemblies

WCF Question. I'm having trouble with multiple assemblies and inheritances and data contracts.
Senario: data contracts binaries are shared
Common.dll
[DataContract]
public abstract class Command
{
[DataMember]
public Guid Id { get; set; }
public Command(Guid id)
{
Id = id;
}
}
assembly1.dll
[DataContract]
public class DeleteStuff : Command
{
public DeleteStuff(Guid id)
: base(id) { }
[DataMember]
public int StuffToDeleteID { get; set; }
}
assembly2.dll
[DataContract]
public class DeleteSomeOtherStuff : Command
{
public DeleteSomeOtherStuff(Guid id)
: base(id) { }
[DataMember]
public int SomeOtherID { get; set; }
}
Service Contract
[ServiceContract]
[ServiceKnownType("GetKnownTypes", typeof(DerivedType))]
public partial interface ICommandsServiceContract
{
[OperationContract]
void Execute(IEnumerable<Command> command);
}
DerivedType class, method GetKnownTypes
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
//Works!*!*! but hard-coded, wont work in big picture since i dont know all the classes
//return new List<Type> { typeof(DeleteSomeOtherStuff), typeof(DeleteStuff) };
//DOESNT WORK!!
Type type = typeof(Command);
IEnumerable<Type> types = AppDomain.CurrentDomain.GetAssemblies().ToList()
.SelectMany(a => a.GetTypes()
.Where(t => type.IsAssignableFrom(t)));
IEnumerable<Type> j = types.ToArray();
return j;
}
If I put a break point on return j; above, when the service first runs it has the correct assembly types that inherit from Command. Then the client spins up and as soon as I send a DeleteSomeOtherStuff to the service it explodes with an error on the SelectMany clause.
Server Error in '/' Application.
Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
Source Error:
Line 25: var type = typeof(Command);
Line 26: var types = AppDomain.CurrentDomain.GetAssemblies().ToList()
Line 27: .SelectMany(a => a.GetTypes())
Line 28: .Where(t => type.IsAssignableFrom(t));
Line 29:
Line 27 is marked as the error.
I tried throwing the array list in a static variable to cache it when the service first runs and then it would be available when its called by a consumer but that had the same error.
I'm using a basic channel factory from the client.
Ideas?? I can't limit to a single assembly.
Thanks!!
In your classes that inherit from Command, add the [KnownType] attribute. For example,
[DataContract]
[KnownType(typeof(Command))]
public class DeleteStuff
{
}