|
New Yorp New Yorp posted:
You could be right, but I can't envision any other way it would be done. I'm trying to setup a library that does a set of operations on a various set of IModel, but the constructor classes for IModel need to be supplied in some way by an external process. The only way I can imagine this happening is though some registration process.
|
# ? Feb 9, 2019 16:22 |
|
|
# ? Jun 8, 2024 03:10 |
|
downout posted:You could be right, but I can't envision any other way it would be done. I'm trying to setup a library that does a set of operations on a various set of IModel, but the constructor classes for IModel need to be supplied in some way by an external process. The only way I can imagine this happening is though some registration process. I'm not sure what you mean by "constructor classes". What does IModelConstructor look like? What do you mean by "an external process"? Marshalled classes through named / unix pipes?
|
# ? Feb 9, 2019 16:41 |
|
Shy posted:time Shy posted:not a particularly complex idea Seriously do whatever you want for your personal learning project but don’t believe this in the context of software.
|
# ? Feb 9, 2019 19:20 |
|
NihilCredo posted:I'm not sure what you mean by "constructor classes". What does IModelConstructor look like? What do you mean by "an external process"? Marshalled classes through named / unix pipes? I'm just calling it a constructor class, that might be a bad name. It's a class with a method that takes an object as a parameter and constructs a poco object and returns it. The method would look like: C# code:
downout fucked around with this message at 23:17 on Feb 9, 2019 |
# ? Feb 9, 2019 20:12 |
|
downout posted:shenanigans There's a serious X/Y smell here. What are you ultimately trying to accomplish?
|
# ? Feb 9, 2019 22:46 |
|
Are you trying to re-create Automapper?
|
# ? Feb 9, 2019 23:05 |
|
FrantzX posted:Are you trying to re-create Automapper? It's similar, and I should probably look into what automapper can do when mapping more complex classes. raminasi posted:There's a serious X/Y smell here. What are you ultimately trying to accomplish? There's lists of various poco classes that I want to put into a cache. The whole cache portion I was trying to build out into a library. The main application that uses the library would need to implement the various poco constructor classes, and then provide them to caching library so it could retrieve the data and update caches when data changes.
|
# ? Feb 9, 2019 23:34 |
|
Cache them as JSON in Redis? Are they not serializable?
|
# ? Feb 9, 2019 23:44 |
|
downout posted:It's similar, and I should probably look into what automapper can do when mapping more complex classes. Well, beware; if you're using AutoMapper to map complex classes, you probably shouldn't be using Automapper. downout posted:There's lists of various poco classes that I want to put into a cache. The whole cache portion I was trying to build out into a library. The main application that uses the library would need to implement the various poco constructor classes, and then provide them to caching library so it could retrieve the data and update caches when data changes. So you're trying to create one cache type that can cache multiple types of object that aren't known at compile time? And the cache is responsible for creating and updating each of these types, so it needs to know how to do it? If I understand correctly (and I very well might not) that seems like a lot of added complexity for I'm not sure what benefit. Why don't you know the set of cacheable types beforehand? Why does the cache need to also do its own object construction/modification?
|
# ? Feb 10, 2019 01:11 |
|
Once you stray from the use case of "I need to convert from a type I don't control to a type I do control" you should be reconsidering AutoMapper IMO. If you're registering a lambda for every conversion you need to do in your app that's a bad smell.
|
# ? Feb 10, 2019 01:16 |
|
raminasi posted:Well, beware; if you're using AutoMapper to map complex classes, you probably shouldn't be using Automapper. That's actually pretty close. The event that triggers the cache can only provide a unique id to get the item that needs updated and a string that identifies the type. I had hoped to make it generic enough that it could use that to get the object that needed updated and add to the cache. It didn't really need to know the type beyond the type implementing a basic interface. To get the object to be updated, I thought it would basically be able to take that string and get a model constructor that implemented an interface with the method it needed. EDIT: Also, the main application would know all of the cacheable types beforehand and implement all the classes to work with them as needed. I got all of this working in the main application, but I had hoped to break it out into it's own stand-alone library because it doesn't seem to need to "know" much about anything it's caching. downout fucked around with this message at 04:22 on Feb 10, 2019 |
# ? Feb 10, 2019 04:20 |
|
The convention in C# is that POCO classes should have a parameterless constructor, which can be expressed by the generic constraint where T : new(), and then be populated through setters, to make it easier to implement serialization. So a very naive generic cache could look like this: code:
What part of this basic design doesn't work for your use case? Also, why can't you entrust to JSON.NET or another library the tricky work of serialization / deserialization, and just implement a string cache in your storage medium of choice? NihilCredo fucked around with this message at 11:09 on Feb 10, 2019 |
# ? Feb 10, 2019 11:07 |
|
raminasi posted:Well, beware; if you're using AutoMapper you probably shouldn't be using Automapper. Fixed that for you. AutoMapper is an abomination that saves you writing some lines of "this.X = that.X" code which 6 months down the line blossoms into a nice garden of "nobody knows how our data transfer objects get filled with data, sprinkle some .Ignore() or .Map() around if it doesn't feel right or just copy-paste one of those existing 50 line Mapping functions that does who knows what".
|
# ? Feb 10, 2019 18:55 |
|
NihilCredo posted:The convention in C# is that POCO classes should have a parameterless constructor, which can be expressed by the generic constraint where T : new(), and then be populated through setters, to make it easier to implement serialization. I wanted to initialize the cache when the application starts, so the way I preferred to try to do that was register a list of types to get with the cache library so it could create each cache type when needed as well as update when needed. And I'll look into string cache, that might work just fine. I hadn't considered it before.
|
# ? Feb 10, 2019 19:21 |
|
EssOEss posted:AutoMapper is an abomination that saves you writing some lines of "this.X = that.X" code which 6 months down the line blossoms into a nice garden of "nobody knows how our data transfer objects get filled with data, sprinkle some .Ignore() or .Map() around if it doesn't feel right or just copy-paste one of those existing 50 line Mapping functions that does who knows what". Pretty much exactly what I was going to write. It's a cool, well-done library, and a neat idea, but once you move beyond a trivial project, the mapping configuration just becomes onerous and difficult to reason about. I know that any Jr. Developer can fix/change a sequence of manual x.foo=y.foo mappings, but they may screw up something in the mapping config that takes hours to track down.
|
# ? Feb 10, 2019 19:22 |
|
Isn't this pretty much all *magic* libraries? Even EF? All the poo poo that gets done under the hood makes stuff hard to reason about.
|
# ? Feb 10, 2019 22:12 |
|
I suppose it is more a question of balancing the cost and benefit. AutoMapper is a particularly outstanding example because the actual benefits are very minimal - I have yet to see a real world project where it would not be less effort to just write this.X = that.X type code. You don't really gain much at all to compensate for the mental overhead it adds. Contrast this with EF, which does hide the SQL generation from you but pays you back with migrations, concurrency conflict handling, LINQ transformations (to a degree), change tracking and whatnot.
|
# ? Feb 11, 2019 05:33 |
|
Okay this is a moon shot but maybe one of the three warlocks that works with the Microsoft Dynamic Language Runtime is reading this and can explain how the plumbing is supposed to work. I am an idiot and have dabbled in created a domain-specific-language that I'm parsing with ANTLR4 using the Visual Studio extensions for it. The impression I got is to to use the ANTLR4 visitor to generate an abstract syntax tree using System.Linq.Expressions and friends. So my test statement turned into a root Expression containing other Expressions for the different math operations for a basic calculator test. I think look at how I hook that up to the DLR and it's just layers and layers and layers and layers and layers containing stuff that seems to have existed before my program even launched and I can't figure it out. I see examples where things are compiled when they run when they compiled when they run and all these other illogical consistencies and loops. So I just kind of bullshitted this: I create a ScriptRuntime for my language I get ScriptEngine for my language from that ScripRuntime I create a ScriptSource using that engine using a one-line string for my test program ...at this point, it's going to my LanguageContext.CompileSourceCode implementation, which is where I use my ANTLR4 stuff to make a System.Linq.Expression root node. I shove this into a ScriptCode subclass I created ...something inside the DLR engine internals knows to call the Run() method on my custom ScriptCode, which is where I run my expression as a lambda Like, is that actually the right loving thing? Is that how this is going down? Am I getting anything at all from this? I kind of expected to have some kind of engine eating up the expressions that had fun features for me. At this point I might as well just make my own little interpreter. Or stop doing this an do something more worth the time like run in traffic with scissors. If anybody's curious, I was seeing what it would take to make a little domain-specific language for NPC scripting in Unity. The commands I have to run deal with having them move here and there and say this and that without halting the entire game look real ugly using Unity's own stuff and IMO state machines are even worse for clarity. So I figured I'd throw a little bit of time at this little bit. PS: Anything you might know about this before, like, 2016 is probably worthless. I've only found one book that was up-to-date and it decided to go to CrazyTown and I think ultimately just drop into IronPython just for shits and giggles. At this point I want to just call the Microsoft DLR "a library for embedding dynamic languages into IronPython." Edit: If you're wondering what half of that has to do with being able to interpret code, so do I. I was kind of expecting to translate to some byte code format or something instead of LINQ Expressions, and I was expecting to feed that into something else. I assumed the DLR would give me some help marshalling .NET objects and a conduit for interactive debugging support; I vaguely recalled that being an advertising point. What I couldn't tell if there was any way to be able to preempt that engine to pause it and run stuff using cooperative multithreading, so this all might just be a dead end. Rocko Bonaparte fucked around with this message at 08:31 on Feb 11, 2019 |
# ? Feb 11, 2019 07:00 |
|
Take a look at F#, it will do scripting and some metaprogramming. Example: https://stackoverflow.com/questions/1156665/how-to-execute-f-code-found-in-a-string-in-a-compiled-f-program You can run your whole shebang in a F# DLL and have it work as a scripting system. Maybe I don't understand what you want. Probably
|
# ? Feb 11, 2019 08:48 |
|
EssOEss posted:I suppose it is more a question of balancing the cost and benefit. AutoMapper is a particularly outstanding example because the actual benefits are very minimal - I have yet to see a real world project where it would not be less effort to just write this.X = that.X type code. You don't really gain much at all to compensate for the mental overhead it adds. I've used AutoMapper quite a bit, and while I think you're understating the benefits somewhat, I broadly agree and probably wouldn't use it in a future project. I actually think you're missing the most important argument against it, which in my opinion is the loss of type safety. The compiler can't stop you from writing Mapper.Map<Foo>(bar) even if there's no mapping from Bar to Foo, or from removing the Bar->Foo mapping code in the mistaken belief that it was unused.
|
# ? Feb 11, 2019 09:47 |
|
Mr Shiny Pants posted:Take a look at F#, it will do scripting and some metaprogramming. I have some specific needs and not just to embed a scripting language. I don't know much at all about F# so I might as well just share. I basically need green threads and coroutines; preferably with the ability to stop the interpreter midway while running stuff and have it resume right there afterwards. It will presumably be rotating through different scripts. Whenever a script has a stopping point, I want it to stop right at that point in that particular routine, and not create a cascade of yields instead. Stuff like that is why I think I need at least my own syntax and then possibly my own interpreter too. I was kind of hoping to dodge the interpreter part by using the DLR. If I could insert instructions every X commands and before major loops then I could basically get green threads, but I don't know if anything the DLR or DLR-related languages is set up to be pre-empted like that. An interpreter meant for this kind of thing could just save its context as a frame somewhere and leave it alone. It would also let me save the progress of these scripts when saving the game because I could serialize the frames.
|
# ? Feb 11, 2019 19:13 |
|
I wanted to thank everyone for their suggestions. My class construction isn't perfect, but it's close to working. One of my biggest problems was that in trying to extract it from an existing project, there was far too much tight coupling and legacy code that was initially pulled over into the library. So, I started reconstructing interfaces for every class and removing all unnecessary methods, etc. Go figure, there was a lot. Anyways, part of the original problems were caused by focusing too much on maintaining how it was working originally instead of the heavy refactor needed to remove all the unnecessary stuff. A bunch of suggestions were hinting around at this, and offered good starting points at what to look.
|
# ? Feb 12, 2019 02:20 |
|
Rocko Bonaparte posted:I have some specific needs and not just to embed a scripting language. I don't know much at all about F# so I might as well just share. I basically need green threads and coroutines; preferably with the ability to stop the interpreter midway while running stuff and have it resume right there afterwards. It will presumably be rotating through different scripts. Whenever a script has a stopping point, I want it to stop right at that point in that particular routine, and not create a cascade of yields instead. Stuff like that is why I think I need at least my own syntax and then possibly my own interpreter too. I was kind of hoping to dodge the interpreter part by using the DLR. If I could insert instructions every X commands and before major loops then I could basically get green threads, but I don't know if anything the DLR or DLR-related languages is set up to be pre-empted like that. An interpreter meant for this kind of thing could just save its context as a frame somewhere and leave it alone. It would also let me save the progress of these scripts when saving the game because I could serialize the frames. Pull up. It sounds more like you’re inventing problems for a technical solution rather than solving for your fundamental complexity. If your goal is to work on that technical problem, that’s fine; also Unity probably isn’t a good engine for that type of work. Especially without source access. Godot is more easily scripted in bespoke ways (check out gdnative) and will let you implement the hooks you’re actually looking for. If you’re fine with losing some of the control of scheduling, you could model your execution environment with state machines. Building a simple FSM lib isn’t hard, but it can easily balloon into emulating some garbage pc architecture if you don’t control the scope. There are some paid unity libs that aren’t completely terrible for that.
|
# ? Feb 12, 2019 13:26 |
|
leper khan posted:Pull up. It sounds more like you’re inventing problems for a technical solution rather than solving for your fundamental complexity. For my personal stuff here, it wouldn't get rammed sideways into Unity but live outside and I'd just have it call into all my own code that generate dialogs, move NPCs, and whatnot. In effect, the scripts would be like little console programs that just make sure my main loop doesn't lock up when it prompts the user for a yes or a no or similar. My problem with essentially creating a State Pattern framework is it's representation is still very disjoint from what I'm feeding it. Something where, say: move here, make a decision, yes path moves north, no path moves south. It's kind of intuitive for me to just write that out in a small script. If it's a state machine, usually that winds up with me drawing out all the circles and arrows on a sheet of paper that doesn't digitize, and then I'm converting that into State objects. So I'm two intermediate representations away from my original thoughts. You could then say I could work on some kind of state machine editor, but if I have to write that then I'm doing goofy poo poo and might as well just be doing that drat interpreter haha. I did see some assets in Unity that looked basically like state machine editors, but got all kinds of mixed reviews on them. They were all also behind paywalls so I'd have to fork over to find out if it even was worth it. In my defense, dabbling in interpreters and language stuff has a secondary purpose: to cut my teeth on something I may want to transition into at my company professionally (not Unity related). It also has actually been enjoyable--at least for the hour or so I blew making the dumbest stack-based interpreter. I blew a bunch of time trying to dodge the interpreter problem but it's naively simple--or it's just that I've blown a lot of my career looking at and working with managed code that this doesn't bother me (yet). Or maybe I should do something more interesting than just the calculator stuff and then report back. I still think it's funny how I remembered my first assignment in my computer architecture class having to do with various machine language syntaxes, and I remember doing the stack-based assignments while thinking it was the biggest bullshit ever. I've ultimately done as much or more in that kind of syntax than I have done with assembler professionally. Where's that guy that does all the stuff in Forth? He's going to pop out of nowhere after this post, right?
|
# ? Feb 12, 2019 18:35 |
|
code:
Hey, at least they fixed it in the next version. Accidentally.
|
# ? Feb 13, 2019 19:11 |
|
Munkeymon posted:
Wow isn't "Action" pretty drat overloaded in the .NET ecosystem? I'm not surprised...
|
# ? Feb 13, 2019 22:40 |
|
Rocko Bonaparte posted:Wow isn't "Action" pretty drat overloaded in the .NET ecosystem? I'm not surprised... I caused it by referencing an enum in Data.Entity in an EF entity. Otherwise it wouldn't have looked in that assembly for names. Still pretty goddamn annoying that nobody ever thought to add a standard attribute to qualify type names.
|
# ? Feb 14, 2019 15:09 |
|
I’ve decided to add scripting to my firewall management app. The reason is that there are things I need to know about a firewall to let me generate rule scripts, create NATs, etc. Basically, I need to know whether a firewall is internet-facing or customer-facing. 90% of the firewalls I manage follow standard naming conventions which I could normally use (i.e, a firewall is internet-facing if it has an interface named ‘extpop’), but the others were acquired as the result of an acquisition. I could hard-code the rules, but that leaves me exposed for the next acquisition. So rather than code that in the app, I’m adding in the ability to execute a script in the factory method that creates a firewall object just before it returns. I’m using C# as my scripting language, because it is surprisingly easy to implement. I’m caching my compiled assemblies, because there is a noticeable overhead for compilation. My question is, once I’m done loading all the firewalls, should I “unload” the cached assemblies? And if so, how? Would clearing the cache dictionary be sufficient or is there something more I should do?
|
# ? Feb 16, 2019 07:46 |
|
IIRC executable code will not get GC’ed, so I don’t think clearing a dictionary is enough. You should load the generated assemblies in their own app domain and then destroy the app domain when you’re done.
|
# ? Feb 17, 2019 19:04 |
|
brap posted:IIRC executable code will not get GC’ed, so I don’t think clearing a dictionary is enough. Thanks for the response. I wasn’t able to find any docs that said whether assemblies are collected, but the whole thing has become moot. Originally, all the firewall models were built at program start, and that was that, so the scripts weren’t needed after. Today I added a “Reload” button, so I think I’ll keep the cached assemblies around.
|
# ? Feb 18, 2019 01:33 |
|
Am I the only one that finds it odd that you have to overload the '>=' and '<=' operators explicitly even if you overload '==', '<' and '>' already? Is there a reason for this besides "that's just the way it is"?
|
# ? Feb 26, 2019 20:20 |
|
LongSack posted:Am I the only one that finds it odd that you have to overload the '>=' and '<=' operators explicitly even if you overload '==', '<' and '>' already? Is there a reason for this besides "that's just the way it is"? I would imagine under the hood they are distinctly different operators (Equals, LessThan, LessThanOrEqualTo, GreaterThan ...) and are handled as such, and the `>=` & `<=` operators aren't just syntactic sugar, if that makes sense. I would find it odd you're overloading operators in the first place
|
# ? Feb 26, 2019 20:38 |
|
LongSack posted:Am I the only one that finds it odd that you have to overload the '>=' and '<=' operators explicitly even if you overload '==', '<' and '>' already? Is there a reason for this besides "that's just the way it is"? That's just the way it is. The whole equality thing is a mess, but at least with those operators, you can implement CompareTo(x, y) and then all of the operators are exactly the same compared to zero. e.g. public static bool operator <(MyType x, MyType y) => CompareTo(x, y) < 0; public static bool operator <=(MyType x, MyType y) => CompareTo(x, y) <= 0; public static bool operator >(MyType x, MyType y) => CompareTo(x, y) > 0; ...etc
|
# ? Feb 26, 2019 20:40 |
|
B-Nasty posted:That's just the way it is. The whole equality thing is a mess, but at least with those operators, you can implement CompareTo(x, y) and then all of the operators are exactly the same compared to zero. e.g. Yeah, that’s how I implement them. Potassium Problems posted:I would find it odd you're overloading operators in the first place Why is that surprising? Two Account objects are equal if they have the same AccountId whether or not the two objects are the same reference. And IComparable<T>, where it makes sense, is something like C# code:
|
# ? Feb 27, 2019 01:34 |
|
LongSack posted:Why is that surprising? Two Account objects are equal if they have the same AccountId whether or not the two objects are the same reference. You might want to be careful with doing something like this. It's an anti-pattern to implement equality operators based around something like a database primary key if there are other properties on the object that can be not-equal. For example, if you have X and Y with the same ID, but you update the AccountName on object Y, is it still accurate to say X.Equals(Y)==true? If you care about the IDs, just do X.AccountId==Y.AccountId so that you intent isn't hidden.
|
# ? Feb 27, 2019 04:00 |
|
Does c# let you mark a class as NotEquatable so that attempting to use == on it will be a compile-time error (instead of defaulting to reference equality)? If that's not possible, better to at least have a consistent convention for object equality.
|
# ? Feb 27, 2019 14:29 |
|
I think you could override the equality operators to throw and mark them deprecated so you'd get a compiler warning but that's not quite what you want.
|
# ? Feb 27, 2019 14:47 |
|
Phone posting here, but what happens to events when a using statement completes? For example Using(var foo = new Foo()) { ... foo.workCompleteZugZug += SomeHandler(...); await foo.DoWork(); } Once that completes, does that clean up properly on dispose? I'm wondering if that leaves behind a reference somewhere.
|
# ? Feb 27, 2019 20:54 |
|
LongSack posted:Why is that surprising? Two Account objects are equal if they have the same AccountId whether or not the two objects are the same reference. And IComparable<T>, where it makes sense, is something like Like B-Nasty said, it easily leads to unclear code, and usually other devs (maybe even yourself, 6 months down the line) will have to dig into the overload code to see what the intent really is. I've seen really obtuse stuff from people who thought they were being super clever. Sanitized example: code:
Potassium Problems fucked around with this message at 21:27 on Feb 27, 2019 |
# ? Feb 27, 2019 21:25 |
|
|
# ? Jun 8, 2024 03:10 |
|
User0015 posted:Phone posting here, but what happens to events when a using statement completes? For example IIRC, that will keep foo from being GC'd. Though I'd feel like it wouldn't be the same issue if you just treated SomeHandler as an Action that Foo takes in its ctor.
|
# ? Feb 27, 2019 22:36 |